Skip to content

Commit ae31d77

Browse files
zoewanggdagnir
andauthored
Transforming S3 PUT override (#5411)
* Transforming S3 PUT override * Fix build and add end to end tests --------- Co-authored-by: Dongie Agnir <[email protected]>
1 parent b1ff244 commit ae31d77

File tree

9 files changed

+329
-20
lines changed

9 files changed

+329
-20
lines changed

test/v2-migration-tests/src/test/resources/maven/after/src/main/java/foo/bar/Application.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@
1515

1616
package foo.bar;
1717

18-
import software.amazon.awssdk.core.exception.SdkException;
1918
import software.amazon.awssdk.services.s3.S3Client;
2019
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
20+
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
21+
import software.amazon.awssdk.services.s3.model.PutObjectResponse;
2122
import software.amazon.awssdk.services.s3.model.S3Object;
2223
import software.amazon.awssdk.services.sqs.SqsClient;
2324
import software.amazon.awssdk.services.sqs.model.QueueDoesNotExistException;
@@ -32,6 +33,8 @@
3233
import java.nio.file.StandardCopyOption;
3334
import software.amazon.awssdk.awscore.exception.AwsServiceException;
3435
import software.amazon.awssdk.core.ResponseInputStream;
36+
import software.amazon.awssdk.core.exception.SdkException;
37+
import software.amazon.awssdk.core.sync.RequestBody;
3538
import software.amazon.awssdk.services.s3.model.GetObjectResponse;
3639

3740
public class Application {
@@ -90,4 +93,11 @@ private static Path downloadFile(S3Client s3, String bucket, String key, Path ds
9093

9194
return dst;
9295
}
96+
97+
private static PutObjectResponse uploadFile(S3Client s3, String bucket, String key, Path source) throws IOException {
98+
PutObjectResponse result = s3.putObject(PutObjectRequest.builder()
99+
.build(), RequestBody.fromFile(source.toFile()));
100+
101+
return result;
102+
}
93103
}

test/v2-migration-tests/src/test/resources/maven/after/src/main/java/foo/bar/Enums.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ public static void main(String... args) {
2929
System.out.println(qan);
3030
System.out.println(qan2);
3131

32-
ReceiveMessageRequest v1Request = ReceiveMessageRequest.builder().build();
32+
ReceiveMessageRequest v1Request = ReceiveMessageRequest.builder()
33+
.build();
3334
List<String> attributes = v1Request.attributeNamesAsStrings();
3435
System.out.println(attributes);
3536

test/v2-migration-tests/src/test/resources/maven/before/src/main/java/foo/bar/Application.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
import com.amazonaws.AmazonServiceException;
2020
import com.amazonaws.services.s3.AmazonS3;
2121
import com.amazonaws.services.s3.model.GetObjectRequest;
22+
import com.amazonaws.services.s3.model.PutObjectRequest;
23+
import com.amazonaws.services.s3.model.PutObjectResult;
2224
import com.amazonaws.services.s3.model.S3Object;
2325
import com.amazonaws.services.sqs.AmazonSQS;
2426
import com.amazonaws.services.sqs.model.AmazonSQSException;
@@ -86,4 +88,10 @@ private static Path downloadFile(AmazonS3 s3, String bucket, String key, Path ds
8688

8789
return dst;
8890
}
91+
92+
private static PutObjectResult uploadFile(AmazonS3 s3, String bucket, String key, Path source) throws IOException {
93+
PutObjectResult result = s3.putObject(bucket, key, source.toFile());
94+
95+
return result;
96+
}
8997
}

v2-migration/src/main/java/software/amazon/awssdk/v2migration/EnumCasingToV2.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,12 @@ public J.Identifier visitIdentifier(J.Identifier identifier, ExecutionContext ct
7676
J.Identifier id = super.visitIdentifier(identifier, ctx);
7777

7878
if (ENUMS.contains(id.getSimpleName())) {
79-
return id.withFieldType(id.getFieldType().withName(id.getSimpleName()));
79+
JavaType.Variable fieldType = id.getFieldType();
80+
if (fieldType == null) {
81+
return id;
82+
}
83+
JavaType.Variable variable = fieldType.withName(id.getSimpleName());
84+
return id.withFieldType(variable);
8085
}
8186

8287
return id;
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.awssdk.v2migration;
17+
18+
import java.util.ArrayList;
19+
import java.util.Arrays;
20+
import java.util.Collections;
21+
import java.util.List;
22+
import java.util.stream.Collectors;
23+
import org.openrewrite.ExecutionContext;
24+
import org.openrewrite.Recipe;
25+
import org.openrewrite.Tree;
26+
import org.openrewrite.TreeVisitor;
27+
import org.openrewrite.java.JavaIsoVisitor;
28+
import org.openrewrite.java.MethodMatcher;
29+
import org.openrewrite.java.tree.Expression;
30+
import org.openrewrite.java.tree.J;
31+
import org.openrewrite.java.tree.JContainer;
32+
import org.openrewrite.java.tree.JRightPadded;
33+
import org.openrewrite.java.tree.JavaType;
34+
import org.openrewrite.java.tree.Space;
35+
import org.openrewrite.java.tree.TypeUtils;
36+
import org.openrewrite.marker.Markers;
37+
import software.amazon.awssdk.annotations.SdkInternalApi;
38+
import software.amazon.awssdk.v2migration.internal.utils.IdentifierUtils;
39+
40+
@SdkInternalApi
41+
public class S3StreamingRequestToV2 extends Recipe {
42+
private static final MethodMatcher PUT_OBJECT =
43+
new MethodMatcher("com.amazonaws.services.s3.AmazonS3 "
44+
+ "putObject(java.lang.String, java.lang.String, java.io.File)",
45+
true);
46+
private static final JavaType.FullyQualified V1_PUT_OBJECT_REQUEST =
47+
TypeUtils.asFullyQualified(JavaType.buildType("com.amazonaws.services.s3.model.PutObjectRequest"));
48+
private static final JavaType.FullyQualified REQUEST_BODY =
49+
TypeUtils.asFullyQualified(JavaType.buildType("software.amazon.awssdk.core.sync.RequestBody"));
50+
51+
@Override
52+
public String getDisplayName() {
53+
return "S3StreamingRequestToV2";
54+
}
55+
56+
@Override
57+
public String getDescription() {
58+
return "S3StreamingRequestToV2.";
59+
}
60+
61+
@Override
62+
public TreeVisitor<?, ExecutionContext> getVisitor() {
63+
return new Visitor();
64+
}
65+
66+
private static final class Visitor extends JavaIsoVisitor<ExecutionContext> {
67+
@Override
68+
public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, ExecutionContext executionContext) {
69+
if (PUT_OBJECT.matches(method, false)) {
70+
method = transformPutFileOverload(method);
71+
}
72+
return super.visitMethodInvocation(method, executionContext);
73+
}
74+
75+
private J.MethodInvocation transformPutFileOverload(J.MethodInvocation method) {
76+
JavaType.Method methodType = method.getMethodType();
77+
if (methodType == null) {
78+
return method;
79+
}
80+
81+
List<Expression> originalArgs = method.getArguments();
82+
83+
Expression bucketExpr = originalArgs.get(0);
84+
Expression keyExpr = originalArgs.get(1);
85+
Expression fileExpr = originalArgs.get(2);
86+
87+
List<Expression> newArgs = new ArrayList<>();
88+
Expression getObjectExpr = bucketAndKeyToPutObject(bucketExpr, keyExpr);
89+
newArgs.add(getObjectExpr);
90+
91+
Space fileArgPrefix = fileExpr.getPrefix();
92+
fileExpr = fileToRequestBody(fileExpr.withPrefix(Space.EMPTY)).withPrefix(fileArgPrefix);
93+
newArgs.add(fileExpr);
94+
95+
List<String> paramNames = Arrays.asList("request", "file");
96+
List<JavaType> paramTypes = newArgs.stream()
97+
.map(Expression::getType)
98+
.collect(Collectors.toList());
99+
100+
101+
methodType = methodType.withParameterTypes(paramTypes)
102+
.withParameterNames(paramNames);
103+
104+
return method.withMethodType(methodType).withArguments(newArgs);
105+
}
106+
107+
private J.MethodInvocation fileToRequestBody(Expression fileExpr) {
108+
maybeAddImport(REQUEST_BODY);
109+
110+
J.Identifier requestBodyId = IdentifierUtils.makeId(REQUEST_BODY.getClassName(), REQUEST_BODY);
111+
112+
JavaType.Method fromFileType = new JavaType.Method(
113+
null,
114+
0L,
115+
REQUEST_BODY,
116+
"fromFile",
117+
REQUEST_BODY,
118+
Collections.singletonList("file"),
119+
Collections.singletonList(JavaType.buildType("java.io.File")),
120+
null,
121+
null
122+
);
123+
124+
J.Identifier fromFileId = IdentifierUtils.makeId("fromFile", fromFileType);
125+
126+
return new J.MethodInvocation(
127+
Tree.randomId(),
128+
Space.EMPTY,
129+
Markers.EMPTY,
130+
JRightPadded.build(requestBodyId),
131+
null,
132+
fromFileId,
133+
JContainer.build(Collections.singletonList(JRightPadded.build(fileExpr))),
134+
fromFileType
135+
);
136+
}
137+
138+
private Expression bucketAndKeyToPutObject(Expression bucketExpr, Expression keyExpr) {
139+
maybeAddImport(V1_PUT_OBJECT_REQUEST);
140+
141+
J.Identifier putObjRequestId = IdentifierUtils.makeId(V1_PUT_OBJECT_REQUEST.getClassName(), V1_PUT_OBJECT_REQUEST);
142+
143+
JavaType.Method ctorType = new JavaType.Method(
144+
null,
145+
0L,
146+
V1_PUT_OBJECT_REQUEST,
147+
"<init>",
148+
V1_PUT_OBJECT_REQUEST,
149+
Arrays.asList("bucket", "key"),
150+
Arrays.asList(bucketExpr.getType(), keyExpr.getType()),
151+
null,
152+
null
153+
);
154+
155+
return new J.NewClass(
156+
Tree.randomId(),
157+
Space.EMPTY,
158+
Markers.EMPTY,
159+
null,
160+
Space.EMPTY,
161+
putObjRequestId.withPrefix(Space.SINGLE_SPACE),
162+
JContainer.build(
163+
Arrays.asList(
164+
JRightPadded.build(bucketExpr),
165+
JRightPadded.build(keyExpr)
166+
)
167+
),
168+
null,
169+
ctorType
170+
);
171+
}
172+
}
173+
}

v2-migration/src/main/resources/META-INF/rewrite/aws-sdk-java-v1-to-v2.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@ tags:
2222
- sdk
2323
recipeList:
2424
- software.amazon.awssdk.v2migration.UpgradeSdkDependencies
25-
- software.amazon.awssdk.v2migration.S3GetObjectConstructorToFluent
2625
- software.amazon.awssdk.v2migration.S3StreamingResponseToV2
26+
- software.amazon.awssdk.v2migration.S3StreamingRequestToV2
27+
- software.amazon.awssdk.v2migration.S3GetObjectConstructorToFluent
28+
- software.amazon.awssdk.v2migration.S3PutObjectConstructorToFluent
2729
- software.amazon.awssdk.v2migration.EnumGettersToV2
2830
- software.amazon.awssdk.v2migration.ChangeSdkType
2931
- software.amazon.awssdk.v2migration.ChangeSdkCoreTypes
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#
2+
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License").
5+
# You may not use this file except in compliance with the License.
6+
# A copy of the License is located at
7+
#
8+
# http://aws.amazon.com/apache2.0
9+
#
10+
# or in the "license" file accompanying this file. This file is distributed
11+
# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
# express or implied. See the License for the specific language governing
13+
# permissions and limitations under the License.
14+
#
15+
---
16+
type: specs.openrewrite.org/v1beta/recipe
17+
name: software.amazon.awssdk.S3PutObjectConstructorToFluent
18+
displayName: Change PutObject constructors to fluent builder calls
19+
recipeList:
20+
- software.amazon.awssdk.migration.internal.recipe.ConstructorToFluent:
21+
clzzFqcn: com.amazonaws.services.s3.model.PutObjectRequest
22+
parameterTypes:
23+
- java.lang.String
24+
- java.lang.String
25+
fluentNames:
26+
- withBucket
27+
- withKey

v2-migration/src/test/java/software/amazon/awssdk/v2migration/EnumGettersToV2Test.java

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,15 @@ void shouldChangeSingleItemEnumGetter() {
6262
" String routeType = phoneNumberInformation.getRouteType();\n" +
6363
" }\n" +
6464
"}\n",
65-
"import software.amazon.awssdk.services.sns.model.PhoneNumberInformation;\n" +
66-
"\n" +
67-
"class Test {\n" +
68-
" static void method() {\n" +
69-
" PhoneNumberInformation phoneNumberInformation = PhoneNumberInformation.builder().build();\n" +
70-
" String routeType = phoneNumberInformation.routeTypeAsString();\n" +
71-
" }\n" +
72-
"}\n"
65+
"import software.amazon.awssdk.services.sns.model.PhoneNumberInformation;\n"
66+
+ "\n"
67+
+ "class Test {\n"
68+
+ " static void method() {\n"
69+
+ " PhoneNumberInformation phoneNumberInformation = PhoneNumberInformation.builder()\n"
70+
+ " .build();\n"
71+
+ " String routeType = phoneNumberInformation.routeTypeAsString();\n"
72+
+ " }\n"
73+
+ "}"
7374
)
7475
);
7576
}
@@ -87,14 +88,15 @@ void shouldChangeCollectionItemEnumGetter() {
8788
" List<String> numberCapabilities = phoneNumberInformation.getNumberCapabilities();\n" +
8889
" }\n" +
8990
"}\n",
90-
"import software.amazon.awssdk.services.sns.model.PhoneNumberInformation;\n" +
91-
"\n" +
92-
"class Test {\n" +
93-
" static void method() {\n" +
94-
" PhoneNumberInformation phoneNumberInformation = PhoneNumberInformation.builder().build();\n" +
95-
" List<String> numberCapabilities = phoneNumberInformation.numberCapabilitiesAsStrings();\n" +
96-
" }\n" +
97-
"}\n"
91+
"import software.amazon.awssdk.services.sns.model.PhoneNumberInformation;\n"
92+
+ "\n"
93+
+ "class Test {\n"
94+
+ " static void method() {\n"
95+
+ " PhoneNumberInformation phoneNumberInformation = PhoneNumberInformation.builder()\n"
96+
+ " .build();\n"
97+
+ " List<String> numberCapabilities = phoneNumberInformation.numberCapabilitiesAsStrings();\n"
98+
+ " }\n"
99+
+ "}"
98100
)
99101
);
100102
}

0 commit comments

Comments
 (0)