Skip to content

Migration tool updates #5495

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Aug 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
package foo.bar;

import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.CreateBucketRequest;
import software.amazon.awssdk.services.s3.model.DeleteBucketRequest;
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.PutObjectResponse;
Expand Down Expand Up @@ -100,4 +102,21 @@ private static PutObjectResponse uploadFile(S3Client s3, String bucket, String k

return result;
}

private static PutObjectResponse uploadString(S3Client s3, String bucket, String key, String content) {
PutObjectResponse result = s3.putObject(PutObjectRequest.builder().bucket(bucket).key(key)
.build(), RequestBody.fromString(content));

return result;
}

private static void createBucket(S3Client s3, String bucket) {
s3.createBucket(CreateBucketRequest.builder().bucket(bucket)
.build());
}

private static void deleteBucket(S3Client s3, String bucket) {
s3.deleteBucket(DeleteBucketRequest.builder().bucket(bucket)
.build());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@
import com.amazonaws.services.s3.model.PutObjectResult;
import com.amazonaws.services.s3.model.S3Object;
import com.amazonaws.services.sqs.AmazonSQS;
import com.amazonaws.services.sqs.model.QueueDoesNotExistException;
import com.amazonaws.services.sqs.model.AmazonSQSException;
import com.amazonaws.services.sqs.model.ListQueuesRequest;
import com.amazonaws.services.sqs.model.ListQueuesResult;

import com.amazonaws.services.sqs.model.QueueDoesNotExistException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
Expand Down Expand Up @@ -94,4 +94,18 @@ private static PutObjectResult uploadFile(AmazonS3 s3, String bucket, String key

return result;
}

private static PutObjectResult uploadString(AmazonS3 s3, String bucket, String key, String content) {
PutObjectResult result = s3.putObject(bucket, key, content);

return result;
}

private static void createBucket(AmazonS3 s3, String bucket) {
s3.createBucket(bucket);
}

private static void deleteBucket(AmazonS3 s3, String bucket) {
s3.deleteBucket(bucket);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

package software.amazon.awssdk.v2migration;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.openrewrite.ExecutionContext;
import org.openrewrite.Recipe;
import org.openrewrite.Tree;
import org.openrewrite.TreeVisitor;
import org.openrewrite.java.JavaIsoVisitor;
import org.openrewrite.java.MethodMatcher;
import org.openrewrite.java.tree.Expression;
import org.openrewrite.java.tree.J;
import org.openrewrite.java.tree.JContainer;
import org.openrewrite.java.tree.JRightPadded;
import org.openrewrite.java.tree.JavaType;
import org.openrewrite.java.tree.Space;
import org.openrewrite.java.tree.TypeUtils;
import org.openrewrite.marker.Markers;
import software.amazon.awssdk.annotations.SdkInternalApi;
import software.amazon.awssdk.v2migration.internal.utils.IdentifierUtils;

@SdkInternalApi
public class S3NonStreamingRequestToV2 extends Recipe {
private static final MethodMatcher CREATE_BUCKET =
new MethodMatcher("com.amazonaws.services.s3.AmazonS3 createBucket(java.lang.String)", true);
private static final MethodMatcher DELETE_BUCKET =
new MethodMatcher("com.amazonaws.services.s3.AmazonS3 deleteBucket(java.lang.String)", true);
private static final JavaType.FullyQualified V1_CREATE_BUCKET_REQUEST =
TypeUtils.asFullyQualified(JavaType.buildType("com.amazonaws.services.s3.model.CreateBucketRequest"));
private static final JavaType.FullyQualified V1_DELETE_BUCKET_REQUEST =
TypeUtils.asFullyQualified(JavaType.buildType("com.amazonaws.services.s3.model.DeleteBucketRequest"));

@Override
public String getDisplayName() {
return "V1 S3 non-streaming requests to V2";
}

@Override
public String getDescription() {
return "Transform usage of V1 S3 non-streaming requests such as CreateBucket and DeleteBucket to V2.";
}

@Override
public TreeVisitor<?, ExecutionContext> getVisitor() {
return new Visitor();
}

private static final class Visitor extends JavaIsoVisitor<ExecutionContext> {
@Override
public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, ExecutionContext executionContext) {
if (CREATE_BUCKET.matches(method, false)) {
method = transformBucketNameArgOverload(method, V1_CREATE_BUCKET_REQUEST);
} else if (DELETE_BUCKET.matches(method, false)) {
method = transformBucketNameArgOverload(method, V1_DELETE_BUCKET_REQUEST);
}
return super.visitMethodInvocation(method, executionContext);
}

private J.MethodInvocation transformBucketNameArgOverload(J.MethodInvocation method, JavaType.FullyQualified fqcn) {
JavaType.Method methodType = method.getMethodType();
if (methodType == null) {
return method;
}

Expression bucketExpr = method.getArguments().get(0);
List<Expression> newArgs = new ArrayList<>();
Expression getObjectExpr = bucketToPojo(bucketExpr, fqcn);
newArgs.add(getObjectExpr);

List<String> paramNames = Collections.singletonList("request");
List<JavaType> paramTypes = newArgs.stream()
.map(Expression::getType)
.collect(Collectors.toList());

methodType = methodType.withParameterTypes(paramTypes)
.withParameterNames(paramNames);

return method.withMethodType(methodType).withArguments(newArgs);
}

private Expression bucketToPojo(Expression bucketExpr, JavaType.FullyQualified fqcn) {
maybeAddImport(fqcn);

J.Identifier putObjRequestId = IdentifierUtils.makeId(fqcn.getClassName(), fqcn);

JavaType.Method ctorType = new JavaType.Method(
null,
0L,
fqcn,
"<init>",
fqcn,
Collections.singletonList("bucket"),
Collections.singletonList(bucketExpr.getType()),
null,
null
);

return new J.NewClass(
Tree.randomId(),
Space.EMPTY,
Markers.EMPTY,
null,
Space.EMPTY,
putObjRequestId.withPrefix(Space.SINGLE_SPACE),
JContainer.build(Collections.singletonList(JRightPadded.build(bucketExpr))),
null,
ctorType
);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,23 +39,26 @@

@SdkInternalApi
public class S3StreamingRequestToV2 extends Recipe {
private static final MethodMatcher PUT_OBJECT =
private static final MethodMatcher PUT_OBJECT_FILE =
new MethodMatcher("com.amazonaws.services.s3.AmazonS3 "
+ "putObject(java.lang.String, java.lang.String, java.io.File)",
true);
+ "putObject(java.lang.String, java.lang.String, java.io.File)", true);
private static final MethodMatcher PUT_OBJECT_STRING =
new MethodMatcher("com.amazonaws.services.s3.AmazonS3 "
+ "putObject(java.lang.String, java.lang.String, java.lang.String)", true);

private static final JavaType.FullyQualified V1_PUT_OBJECT_REQUEST =
TypeUtils.asFullyQualified(JavaType.buildType("com.amazonaws.services.s3.model.PutObjectRequest"));
private static final JavaType.FullyQualified REQUEST_BODY =
TypeUtils.asFullyQualified(JavaType.buildType("software.amazon.awssdk.core.sync.RequestBody"));

@Override
public String getDisplayName() {
return "S3StreamingRequestToV2";
return "V1 S3 streaming requests to V2";
}

@Override
public String getDescription() {
return "S3StreamingRequestToV2.";
return "Transform usage of V1 S3 streaming requests such as PutObject to V2.";
}

@Override
Expand All @@ -66,12 +69,78 @@ public TreeVisitor<?, ExecutionContext> getVisitor() {
private static final class Visitor extends JavaIsoVisitor<ExecutionContext> {
@Override
public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, ExecutionContext executionContext) {
if (PUT_OBJECT.matches(method, false)) {
if (PUT_OBJECT_FILE.matches(method, false)) {
method = transformPutFileOverload(method);
} else if (PUT_OBJECT_STRING.matches(method, false)) {
method = transformPutStringOverload(method);
}
return super.visitMethodInvocation(method, executionContext);
}

private J.MethodInvocation transformPutStringOverload(J.MethodInvocation method) {
JavaType.Method methodType = method.getMethodType();
if (methodType == null) {
return method;
}

List<Expression> originalArgs = method.getArguments();

Expression bucketExpr = originalArgs.get(0);
Expression keyExpr = originalArgs.get(1);
Expression stringExpr = originalArgs.get(2);

List<Expression> newArgs = new ArrayList<>();
Expression getObjectExpr = bucketAndKeyToPutObject(bucketExpr, keyExpr);
newArgs.add(getObjectExpr);

// This is to maintain the formatting/spacing of original code, getPrefix() retrieves the leading whitespace
Space stringArgPrefix = stringExpr.getPrefix();
stringExpr = stringToRequestBody(stringExpr.withPrefix(Space.EMPTY)).withPrefix(stringArgPrefix);
newArgs.add(stringExpr);

List<String> paramNames = Arrays.asList("request", "stringContent");
List<JavaType> paramTypes = newArgs.stream()
.map(Expression::getType)
.collect(Collectors.toList());


methodType = methodType.withParameterTypes(paramTypes)
.withParameterNames(paramNames);

return method.withMethodType(methodType).withArguments(newArgs);
}

private J.MethodInvocation stringToRequestBody(Expression fileExpr) {
maybeAddImport(REQUEST_BODY);

J.Identifier requestBodyId = IdentifierUtils.makeId(REQUEST_BODY.getClassName(), REQUEST_BODY);

JavaType.Method fromStringType = new JavaType.Method(
null,
0L,
REQUEST_BODY,
"fromString",
REQUEST_BODY,
Collections.singletonList("stringContent"),
Collections.singletonList(JavaType.buildType("java.lang.String")),
null,
null
);

J.Identifier fromFileId = IdentifierUtils.makeId("fromString", fromStringType);

return new J.MethodInvocation(
Tree.randomId(),
Space.EMPTY,
Markers.EMPTY,
JRightPadded.build(requestBodyId),
null,
fromFileId,
JContainer.build(Collections.singletonList(JRightPadded.build(fileExpr))),
fromStringType
);
}

private J.MethodInvocation transformPutFileOverload(J.MethodInvocation method) {
JavaType.Method methodType = method.getMethodType();
if (methodType == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ recipeList:
- software.amazon.awssdk.v2migration.UpgradeSdkDependencies
- software.amazon.awssdk.v2migration.S3StreamingResponseToV2
- software.amazon.awssdk.v2migration.S3StreamingRequestToV2
- software.amazon.awssdk.v2migration.S3GetObjectConstructorToFluent
- software.amazon.awssdk.v2migration.S3PutObjectConstructorToFluent
- software.amazon.awssdk.v2migration.S3NonStreamingRequestToV2
- software.amazon.awssdk.v2migration.S3MethodsConstructorToFluent
- software.amazon.awssdk.v2migration.EnumGettersToV2
- software.amazon.awssdk.v2migration.ChangeSdkType
- software.amazon.awssdk.v2migration.ChangeSdkCoreTypes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
#
---
type: specs.openrewrite.org/v1beta/recipe
name: software.amazon.awssdk.v2migration.S3GetObjectConstructorToFluent
displayName: Change GetObject constructors to fluent builder calls
name: software.amazon.awssdk.v2migration.S3MethodsConstructorToFluent
displayName: Change S3 method constructors to fluent builder calls
recipeList:
- software.amazon.awssdk.v2migration.ConstructorToFluent:
clzzFqcn: com.amazonaws.services.s3.model.GetObjectRequest
Expand All @@ -24,4 +24,24 @@ recipeList:
- java.lang.String
fluentNames:
- withBucket
- withKey
- withKey
- software.amazon.awssdk.v2migration.ConstructorToFluent:
clzzFqcn: com.amazonaws.services.s3.model.PutObjectRequest
parameterTypes:
- java.lang.String
- java.lang.String
fluentNames:
- withBucket
- withKey
- software.amazon.awssdk.v2migration.ConstructorToFluent:
clzzFqcn: com.amazonaws.services.s3.model.CreateBucketRequest
parameterTypes:
- java.lang.String
fluentNames:
- withBucket
- software.amazon.awssdk.v2migration.ConstructorToFluent:
clzzFqcn: com.amazonaws.services.s3.model.DeleteBucketRequest
parameterTypes:
- java.lang.String
fluentNames:
- withBucket

This file was deleted.

Loading
Loading