Skip to content

Migration tool recipe for adding comments for unsupported methods #6195

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 4 commits into from
Jun 20, 2025
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 @@ -28,16 +28,22 @@
import software.amazon.awssdk.transfer.s3.model.Copy;
import software.amazon.awssdk.transfer.s3.model.CopyRequest;
import software.amazon.awssdk.transfer.s3.model.DirectoryDownload;
import software.amazon.awssdk.transfer.s3.model.DirectoryUpload;
import software.amazon.awssdk.transfer.s3.model.DownloadDirectoryRequest;
import software.amazon.awssdk.transfer.s3.model.DownloadFileRequest;
import software.amazon.awssdk.transfer.s3.model.FileDownload;
import software.amazon.awssdk.transfer.s3.model.FileUpload;
import software.amazon.awssdk.transfer.s3.model.ResumableFileDownload;
import software.amazon.awssdk.transfer.s3.model.ResumableFileUpload;
import software.amazon.awssdk.transfer.s3.model.ResumableTransfer;
import software.amazon.awssdk.transfer.s3.model.UploadDirectoryRequest;
import software.amazon.awssdk.transfer.s3.model.UploadFileRequest;
import software.amazon.awssdk.transfer.s3.model.UploadRequest;
import software.amazon.awssdk.transfer.s3.progress.TransferProgress;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.time.Duration;

public class TransferManagerS3 {
Expand Down Expand Up @@ -93,8 +99,19 @@ void downloadDirectory(S3TransferManager tm, File destination) {
tm.close();
}

void uploadDirectory(S3TransferManager tm) {
DirectoryUpload fileUpload1 = tm.uploadDirectory(UploadDirectoryRequest.builder().bucket("bucket").s3Prefix("prefix").source(file.toPath()).maxDepth(true ? Integer.MAX_VALUE : 1).build());
}

void resume(S3TransferManager tm, ResumableFileDownload persistableDownload, ResumableFileUpload persistableUpload) {
FileDownload download = tm.resumeDownloadFile(persistableDownload);
FileUpload upload = tm.resumeUploadFile(persistableUpload);
}
}

void POJO_methods(ResumableTransfer transfer, OutputStream outputStream, TransferProgress progress) throws IOException {
String s = transfer.serializeToString();
transfer.serializeToOutputStream(outputStream);

long bytesTransferred = progress.snapshot().transferredBytes();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,17 @@
import com.amazonaws.services.s3.transfer.Copy;
import com.amazonaws.services.s3.transfer.Download;
import com.amazonaws.services.s3.transfer.MultipleFileDownload;
import com.amazonaws.services.s3.transfer.MultipleFileUpload;
import com.amazonaws.services.s3.transfer.PersistableDownload;
import com.amazonaws.services.s3.transfer.PersistableTransfer;
import com.amazonaws.services.s3.transfer.PersistableUpload;
import com.amazonaws.services.s3.transfer.TransferManager;
import com.amazonaws.services.s3.transfer.TransferManagerBuilder;
import com.amazonaws.services.s3.transfer.TransferProgress;
import com.amazonaws.services.s3.transfer.Upload;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;

public class TransferManagerS3 {

Expand Down Expand Up @@ -78,8 +83,19 @@ void downloadDirectory(TransferManager tm, File destination) {
tm.shutdownNow();
}

void uploadDirectory(TransferManager tm) {
MultipleFileUpload fileUpload1 = tm.uploadDirectory("bucket", "prefix", file, true);
}

void resume(TransferManager tm, PersistableDownload persistableDownload, PersistableUpload persistableUpload) {
Download download = tm.resumeDownload(persistableDownload);
Upload upload = tm.resumeUpload(persistableUpload);
}
}

void POJO_methods(PersistableTransfer transfer, OutputStream outputStream, TransferProgress progress) throws IOException {
String s = transfer.serialize();
transfer.serialize(outputStream);

long bytesTransferred = progress.getBytesTransferred();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ public class S3AddImportsAndComments extends Recipe {
private static final MethodMatcher GET_EXPIRY_TIME = v1EnMethodMatcher("S3EventNotification.RestoreEventDataEntity "
+ "getLifecycleRestorationExpiryTime(..)");


private static final Pattern CANNED_ACL = Pattern.compile(V1_S3_MODEL_PKG + "CannedAccessControlList");
private static final Pattern GET_OBJECT_REQUEST = Pattern.compile(V1_S3_MODEL_PKG + "GetObjectRequest");
private static final Pattern CREATE_BUCKET_REQUEST = Pattern.compile(V1_S3_MODEL_PKG + "CreateBucketRequest");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
* 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 static software.amazon.awssdk.v2migration.internal.utils.S3TransformUtils.V1_TM_PKG;
import static software.amazon.awssdk.v2migration.internal.utils.S3TransformUtils.V2_S3_CLIENT;
import static software.amazon.awssdk.v2migration.internal.utils.S3TransformUtils.V2_S3_MODEL_PKG;
import static software.amazon.awssdk.v2migration.internal.utils.S3TransformUtils.V2_TM_CLIENT;
import static software.amazon.awssdk.v2migration.internal.utils.S3TransformUtils.createComments;
import static software.amazon.awssdk.v2migration.internal.utils.S3TransformUtils.v2TmMethodMatcher;

import java.util.regex.Pattern;
import org.openrewrite.ExecutionContext;
import org.openrewrite.Recipe;
import org.openrewrite.TreeVisitor;
import org.openrewrite.java.JavaIsoVisitor;
import org.openrewrite.java.MethodMatcher;
import org.openrewrite.java.tree.J;
import org.openrewrite.java.tree.JavaType;
import software.amazon.awssdk.annotations.SdkInternalApi;

@SdkInternalApi
public class S3TmAddComments extends Recipe {

private static final Pattern S3_TM = Pattern.compile(V2_TM_CLIENT);
private static final Pattern S3_CLIENT = Pattern.compile(V2_S3_CLIENT);

private static final MethodMatcher COPY = v2TmMethodMatcher("copy(..)");
private static final MethodMatcher DOWNLOAD = v2TmMethodMatcher(String.format("download(%sGetObjectRequest, java.io.File, "
+ "%sinternal.S3ProgressListener, ..)",
V2_S3_MODEL_PKG, V1_TM_PKG));
private static final MethodMatcher DOWNLOAD_DIRECTORY = v2TmMethodMatcher("downloadDirectory(..)");
private static final MethodMatcher UPLOAD = v2TmMethodMatcher("upload(..)");
private static final MethodMatcher UPLOAD_DIRECTORY = v2TmMethodMatcher("uploadDirectory(..)");

@Override
public String getDisplayName() {
return "Add imports and comments to unsupported S3 transfer manager transforms.";
}

@Override
public String getDescription() {
return "Add imports and comments to unsupported S3 transfer manager transforms.";
}

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

private static class Visitor extends JavaIsoVisitor<ExecutionContext> {

@Override
public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) {
if (COPY.matches(method) && (method.getArguments().size() == 2 || method.getArguments().size() == 3)) {
String comment = "Migration for TransferStateChangeListener is not supported by the migration tool. Please "
+ "manually migrate the code using TransferListener in v2";
return method.withComments(createComments(comment));
}
if (DOWNLOAD.matches(method)) {
String comment = "Migration for S3ProgressListener is not supported by the migration tool. Please manually "
+ "migrate the code using TransferListener in v2";
return method.withComments(createComments(comment));
}
if (DOWNLOAD_DIRECTORY.matches(method) && method.getArguments().size() > 3) {
String comment = "Migration for KeyFilter is not supported by the migration tool. Please "
+ "manually migrate the code using DownloadFilter in v2";
return method.withComments(createComments(comment));
}
if (UPLOAD.matches(method) && method.getArguments().size() == 4) {
String comment = "Migration for InputStream and ObjectMetadata as argument for upload is not supported by the "
+ "migration tool.";
return method.withComments(createComments(comment));
}
if (UPLOAD.matches(method) && method.getArguments().size() == 2) {
String comment = "Migration for S3ProgressListener is not supported by the migration tool. Please manually "
+ "migrate the code using TransferListener in v2";
return method.withComments(createComments(comment));
}
if (UPLOAD_DIRECTORY.matches(method) && method.getArguments().size() > 4) {
String comment = "Migration for ObjectMetadataProvider as argument for uploadDirectory is not supported by the "
+ "migration tool.";
return method.withComments(createComments(comment));
}

return method;
}

@Override
public J.NewClass visitNewClass(J.NewClass newClass, ExecutionContext ctx) {
JavaType type = newClass.getType();
if (!(type instanceof JavaType.FullyQualified)) {
return newClass;
}

if (type.isAssignableFrom(S3_TM) &&
!newClass.getArguments().isEmpty() &&
newClass.getArguments().get(0).getType() != null) {
if (newClass.getArguments().get(0).getType().isAssignableFrom(S3_CLIENT)) {
String comment = "S3TransferManager requires S3AsyncClient in v2. Please create a new S3AsyncClient "
+ "instance for v2 S3TransferManager.";
return newClass.withComments(createComments(comment));
}
}

return newClass;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ public class TransferManagerMethodsToV2 extends Recipe {

private static final MethodMatcher DOWNLOAD_DIR = v2TmMethodMatcher("downloadDirectory(String, String, java.io.File)");

private static final MethodMatcher UPLOAD_DIR = v2TmMethodMatcher("uploadDirectory(String, String, java.io.File, boolean)");

private static final Pattern S3_TM_CREDENTIAL = Pattern.compile(V2_TM_CLIENT);
private static final Pattern V2_AWSCREDENTAIL = Pattern.compile("software.amazon.awssdk.auth.credentials.AwsCredentials");
private static final Pattern V2_CREDENTIAL_PROVIDER = Pattern.compile("software.amazon.awssdk.auth.credentials"
Expand Down Expand Up @@ -110,6 +112,10 @@ public J visitMethodInvocation(J.MethodInvocation method, ExecutionContext execu
method = transformDownloadDirectory(method);
return super.visitMethodInvocation(method, executionContext);
}
if (UPLOAD_DIR.matches(method, false)) {
method = transformUploadDirectory(method);
return super.visitMethodInvocation(method, executionContext);
}

return super.visitMethodInvocation(method, executionContext);
}
Expand Down Expand Up @@ -165,11 +171,24 @@ private J.MethodInvocation transformDownloadDirectory(J.MethodInvocation method)
method.getArguments().get(0), method.getArguments().get(1),
method.getArguments().get(2));

addTmImport("DirectoryDownload");
addTmImport("DownloadDirectoryRequest");
return method;
}

private J.MethodInvocation transformUploadDirectory(J.MethodInvocation method) {
String v2Method = "#{any()}.uploadDirectory(UploadDirectoryRequest.builder()"
+ ".bucket(#{any()}).s3Prefix(#{any()}).source(#{any()}.toPath())"
+ ".maxDepth(#{any()} ? Integer.MAX_VALUE : 1).build())";

method = JavaTemplate.builder(v2Method).build()
.apply(getCursor(), method.getCoordinates().replace(), method.getSelect(),
method.getArguments().get(0), method.getArguments().get(1),
method.getArguments().get(2), method.getArguments().get(3));

addTmImport("UploadDirectoryRequest");
return method;
}

private J.MethodInvocation transformUploadWithBucketKeyFile(J.MethodInvocation method) {
String v2Method = "#{any()}.uploadFile(UploadFileRequest.builder()"
+ ".putObjectRequest(PutObjectRequest.builder().bucket(#{any()}).key(#{any()}).build())"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public final class S3TransformUtils {
public static final String V1_S3_MODEL_PKG = "com.amazonaws.services.s3.model.";
public static final String V1_S3_PKG = "com.amazonaws.services.s3.";
public static final String V1_EN_PKG = "com.amazonaws.services.s3.event.";
public static final String V1_TM_PKG = "com.amazonaws.services.s3.transfer.";

public static final String V2_S3_CLIENT = "software.amazon.awssdk.services.s3.S3Client";
public static final String V2_S3_MODEL_PKG = "software.amazon.awssdk.services.s3.model.";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,6 @@ recipeList:
- software.amazon.awssdk.v2migration.S3NonStreamingRequestToV2Complex
- software.amazon.awssdk.v2migration.S3PutObjectRequestToV2
- software.amazon.awssdk.v2migration.SettersToBuilderV2
- software.amazon.awssdk.v2migration.S3TmAddComments
- software.amazon.awssdk.v2migration.ChangeTransferManagerSimpleMethods
- software.amazon.awssdk.v2migration.TransferManagerMethodsToV2
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,22 @@ recipeList:
newMethodName: resumeUploadFile
- org.openrewrite.java.ChangeMethodName:
methodPattern: software.amazon.awssdk.transfer.s3.S3TransferManager shutdownNow()
newMethodName: close
newMethodName: close
- org.openrewrite.java.ChangeMethodName:
methodPattern: software.amazon.awssdk.transfer.s3.model.Transfer getProgress()
newMethodName: progress
- org.openrewrite.java.ChangeMethodName:
methodPattern: software.amazon.awssdk.transfer.s3.model.ResumableTransfer serialize()
newMethodName: serializeToString
- org.openrewrite.java.ChangeMethodName:
methodPattern: software.amazon.awssdk.transfer.s3.model.ResumableTransfer serialize(java.io.OutputStream)
newMethodName: serializeToOutputStream
- org.openrewrite.java.ChangeMethodName:
methodPattern: software.amazon.awssdk.transfer.s3.progress.TransferProgress getBytesTransferred()
newMethodName: snapshot().transferredBytes
- org.openrewrite.java.ChangeMethodName:
methodPattern: software.amazon.awssdk.transfer.s3.progress.TransferProgress getTotalBytesToTransfer()
newMethodName: snapshot().totalBytes
- org.openrewrite.java.ChangeMethodName:
methodPattern: software.amazon.awssdk.transfer.s3.progress.TransferProgress getPercentTransferred()
newMethodName: snapshot().ratioTransferred