Skip to content

Commit dee425c

Browse files
committed
Transforming S3 PUT override
1 parent b1ff244 commit dee425c

File tree

4 files changed

+284
-1
lines changed

4 files changed

+284
-1
lines changed
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
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
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 static org.openrewrite.java.Assertions.java;
19+
20+
import org.junit.jupiter.api.Test;
21+
import org.junit.jupiter.api.condition.EnabledOnJre;
22+
import org.junit.jupiter.api.condition.JRE;
23+
import org.openrewrite.java.Java8Parser;
24+
import org.openrewrite.test.RecipeSpec;
25+
import org.openrewrite.test.RewriteTest;
26+
27+
public class S3StreamingRequestToV2Test implements RewriteTest {
28+
@Override
29+
public void defaults(RecipeSpec spec) {
30+
spec.recipe(new S3StreamingRequestToV2());
31+
spec.parser(Java8Parser.builder().classpath(
32+
"aws-java-sdk-s3",
33+
"aws-java-sdk-core",
34+
"s3",
35+
"sdk-core",
36+
"aws-core"));
37+
}
38+
39+
@Test
40+
@EnabledOnJre({JRE.JAVA_8})
41+
public void testS3PutObjectOverrideRewrite() {
42+
rewriteRun(
43+
java(
44+
"import com.amazonaws.services.s3.AmazonS3Client;\n"
45+
+ "\n"
46+
+ "import java.io.File;\n"
47+
+ "\n"
48+
+ "public class S3PutObjectExample {\n"
49+
+ " private static final String BUCKET = \"my-bucket\";\n"
50+
+ " private static final String KEY = \"key\";\n"
51+
+ "\n"
52+
+ " public static void main(String[] args) {\n"
53+
+ " AmazonS3Client s3 = null;\n"
54+
+ "\n"
55+
+ " File myFile = new File(\"test.txt\");\n"
56+
+ "\n"
57+
+ " s3.putObject(BUCKET, KEY, myFile);\n"
58+
+ " }\n"
59+
+ "}\n",
60+
"import com.amazonaws.services.s3.AmazonS3Client;\n"
61+
+ "import com.amazonaws.services.s3.model.PutObjectRequest;\n"
62+
+ "import software.amazon.awssdk.core.sync.RequestBody;\n"
63+
+ "\n"
64+
+ "import java.io.File;\n"
65+
+ "\n"
66+
+ "public class S3PutObjectExample {\n"
67+
+ " private static final String BUCKET = \"my-bucket\";\n"
68+
+ " private static final String KEY = \"key\";\n"
69+
+ "\n"
70+
+ " public static void main(String[] args) {\n"
71+
+ " AmazonS3Client s3 = null;\n"
72+
+ "\n"
73+
+ " File myFile = new File(\"test.txt\");\n"
74+
+ "\n"
75+
+ " s3.putObject(new PutObjectRequest(BUCKET, KEY), RequestBody.fromFile(myFile));\n"
76+
+ " }\n"
77+
+ "}"
78+
)
79+
);
80+
}
81+
}

0 commit comments

Comments
 (0)