Skip to content

Added support for s3-event-notifications in migration tool #6059

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 18 commits into from
May 2, 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 @@ -46,6 +46,11 @@
<artifactId>s3</artifactId>
<version>V2_VERSION</version>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3-event-notifications</artifactId>
<version>V2_VERSION</version>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3-transfer-manager</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* 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 foo.bar;
import software.amazon.awssdk.eventnotifications.s3.model.S3EventNotification;
import software.amazon.awssdk.eventnotifications.s3.model.S3EventNotificationRecord;
import software.amazon.awssdk.eventnotifications.s3.model.RestoreEventData;
import software.amazon.awssdk.eventnotifications.s3.model.GlacierEventData;
import org.joda.time.DateTime;

public class S3EnDateTime {

public void parseEvent(String jsonInput) {
S3EventNotification notification = S3EventNotification.fromJson(jsonInput);

for (S3EventNotification.S3EventNotificationRecord record : notification.getRecords()) {
DateTime eventTime = /*AWS SDK for Java v2 migration: getEventTime returns Instant instead of DateTime in v2. AWS SDK v2 does not include org.joda.time as a dependency. If you want to keep using DateTime, you'll need to manually add "org.joda.time:joda-time" dependency to your project after migration.*/new DateTime(record.getEventTime().toEpochMilli());

GlacierEventData glacierEventData = record.getGlacierEventData();

RestoreEventData restoreEventData = glacierEventData.getRestoreEventData();

DateTime expireTime = /*AWS SDK for Java v2 migration: getLifecycleRestorationExpiryTime returns Instant instead of DateTime in v2. AWS SDK v2 does not include org.joda.time as a dependency. If you want to keep using DateTime, you'll need to manually add "org.joda.time:joda-time" dependency to your project after migration.*/new DateTime(restoreEventData.getLifecycleRestorationExpiryTime().toEpochMilli());

}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,6 @@
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;
Expand All @@ -34,6 +30,11 @@
import software.amazon.awssdk.transfer.s3.S3TransferManager;
import software.amazon.awssdk.transfer.s3.model.UploadRequest;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.net.URL;
import java.util.Date;

public class S3Transforms {

S3Client s3;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* 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 foo.bar;

import com.amazonaws.services.s3.event.S3EventNotification;
import com.amazonaws.services.s3.event.S3EventNotification.S3EventNotificationRecord;
import com.amazonaws.services.s3.event.S3EventNotification.RestoreEventDataEntity;
import com.amazonaws.services.s3.event.S3EventNotification.GlacierEventDataEntity;
import com.amazonaws.services.s3.model.S3Event;
import org.joda.time.DateTime;

public class S3EnDateTime {

public void parseEvent(String jsonInput) {
S3EventNotification notification = S3EventNotification.parseJson(jsonInput);

for (S3EventNotification.S3EventNotificationRecord record : notification.getRecords()) {
DateTime eventTime = record.getEventTime();

GlacierEventDataEntity glacierEventData = record.getGlacierEventData();

RestoreEventDataEntity restoreEventData = glacierEventData.getRestoreEventData();

DateTime expireTime = restoreEventData.getLifecycleRestorationExpiryTime();

}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@
<artifactId>netty-nio-client</artifactId>
<version>V2_VERSION</version>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3-event-notifications</artifactId>
<version>V2_VERSION</version>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* 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 foo.bar;

import software.amazon.awssdk.eventnotifications.s3.model.S3Bucket;
import software.amazon.awssdk.eventnotifications.s3.model.S3EventNotification;
import software.amazon.awssdk.eventnotifications.s3.model.S3;
import software.amazon.awssdk.eventnotifications.s3.model.S3EventNotificationRecord;
import software.amazon.awssdk.eventnotifications.s3.model.S3Object;
import software.amazon.awssdk.eventnotifications.s3.model.RequestParameters;
import software.amazon.awssdk.eventnotifications.s3.model.ResponseElements;
import software.amazon.awssdk.eventnotifications.s3.model.RestoreEventData;
import software.amazon.awssdk.eventnotifications.s3.model.UserIdentity;
import software.amazon.awssdk.eventnotifications.s3.model.GlacierEventData;
import software.amazon.awssdk.eventnotifications.s3.model.LifecycleEventData;
import software.amazon.awssdk.eventnotifications.s3.model.IntelligentTieringEventData;
import software.amazon.awssdk.eventnotifications.s3.model.ReplicationEventData;

public class S3EventNotificationTest {
public void parseEvent(String jsonInput) {
S3EventNotification notification = S3EventNotification.fromJson(jsonInput);

for (S3EventNotificationRecord record : notification.getRecords()) {
S3 s3 = record.getS3();

S3Bucket bucket = s3.getBucket();

S3Object object = s3.getObject();

String eventName = record.getEventName();

String eventNameEnum = record.getEventName();

RequestParameters requestParams = record.getRequestParameters();

ResponseElements responseElements = record.getResponseElements();

UserIdentity userIdentity = record.getUserIdentity();

GlacierEventData glacierEventData = record.getGlacierEventData();

RestoreEventData restoreEventData = glacierEventData.getRestoreEventData();

LifecycleEventData lifecycleEventData = record.getLifecycleEventData();

IntelligentTieringEventData intelligentTieringEventData = record.getIntelligentTieringEventData();

ReplicationEventData replicationEventData = record.getReplicationEventData();
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* 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 foo.bar;

import com.amazonaws.services.s3.event.S3EventNotification;
import com.amazonaws.services.s3.event.S3EventNotification.S3BucketEntity;
import com.amazonaws.services.s3.event.S3EventNotification.S3Entity;
import com.amazonaws.services.s3.event.S3EventNotification.S3EventNotificationRecord;
import com.amazonaws.services.s3.event.S3EventNotification.S3ObjectEntity;
import com.amazonaws.services.s3.event.S3EventNotification.RequestParametersEntity;
import com.amazonaws.services.s3.event.S3EventNotification.ResponseElementsEntity;
import com.amazonaws.services.s3.event.S3EventNotification.RestoreEventDataEntity;
import com.amazonaws.services.s3.event.S3EventNotification.UserIdentityEntity;
import com.amazonaws.services.s3.event.S3EventNotification.GlacierEventDataEntity;
import com.amazonaws.services.s3.event.S3EventNotification.LifecycleEventDataEntity;
import com.amazonaws.services.s3.event.S3EventNotification.IntelligentTieringEventDataEntity;
import com.amazonaws.services.s3.event.S3EventNotification.ReplicationEventDataEntity;
import com.amazonaws.services.s3.model.S3Event;

public class S3EventNotificationTest {
public void parseEvent(String jsonInput) {
S3EventNotification notification = S3EventNotification.parseJson(jsonInput);

for (S3EventNotificationRecord record : notification.getRecords()) {
S3Entity s3 = record.getS3();

S3BucketEntity bucket = s3.getBucket();

S3ObjectEntity object = s3.getObject();

String eventName = record.getEventName();

S3Event eventNameEnum = record.getEventNameAsEnum();

RequestParametersEntity requestParams = record.getRequestParameters();

ResponseElementsEntity responseElements = record.getResponseElements();

UserIdentityEntity userIdentity = record.getUserIdentity();

GlacierEventDataEntity glacierEventData = record.getGlacierEventData();

RestoreEventDataEntity restoreEventData = glacierEventData.getRestoreEventData();

LifecycleEventDataEntity lifecycleEventData = record.getLifecycleEventData();

IntelligentTieringEventDataEntity intelligentTieringEventData = record.getIntelligentTieringEventData();

ReplicationEventDataEntity replicationEventData = record.getReplicationEventDataEntity();
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import static software.amazon.awssdk.v2migration.internal.utils.S3TransformUtils.V1_S3_MODEL_PKG;
import static software.amazon.awssdk.v2migration.internal.utils.S3TransformUtils.V2_S3_MODEL_PKG;
import static software.amazon.awssdk.v2migration.internal.utils.S3TransformUtils.createComments;
import static software.amazon.awssdk.v2migration.internal.utils.S3TransformUtils.v1EnMethodMatcher;
import static software.amazon.awssdk.v2migration.internal.utils.S3TransformUtils.v1S3MethodMatcher;

import java.util.List;
Expand Down Expand Up @@ -52,6 +53,10 @@ public class S3AddImportsAndComments extends Recipe {
private static final MethodMatcher SELECT_OBJECT_CONTENT = v1S3MethodMatcher("selectObjectContent(..)");
private static final MethodMatcher SET_LIFECYCLE_CONFIGURATION = v1S3MethodMatcher("setBucketLifecycleConfiguration(..)");
private static final MethodMatcher SET_TAGGING_CONFIGURATION = v1S3MethodMatcher("setBucketTaggingConfiguration(..)");
private static final MethodMatcher GET_EVENT_TIME = v1EnMethodMatcher("S3EventNotification.S3EventNotificationRecord "
+ "getEventTime(..)");
private static final MethodMatcher GET_EXPIRY_TIME = v1EnMethodMatcher("S3EventNotification.RestoreEventDataEntity "
+ "getLifecycleRestorationExpiryTime(..)");


private static final Pattern CANNED_ACL = Pattern.compile(V1_S3_MODEL_PKG + "CannedAccessControlList");
Expand Down Expand Up @@ -191,6 +196,13 @@ public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, Execu
return method.withComments(createComments(comment));
}

if (GET_EVENT_TIME.matches(method) || GET_EXPIRY_TIME.matches(method)) {
String comment = method.getSimpleName() + " returns Instant instead of DateTime in v2. AWS SDK v2 does not "
+ "include org.joda.time as a dependency. If you want to keep using DateTime, you'll need to "
+ "manually add \"org.joda.time:joda-time\" dependency to your"
+ " project after migration.";
return method.withComments(createComments(comment));
}
return method;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* 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.v1EnMethodMatcher;

import org.openrewrite.ExecutionContext;
import org.openrewrite.Recipe;
import org.openrewrite.TreeVisitor;
import org.openrewrite.java.JavaTemplate;
import org.openrewrite.java.JavaVisitor;
import org.openrewrite.java.MethodMatcher;
import org.openrewrite.java.tree.J;
import software.amazon.awssdk.annotations.SdkInternalApi;

@SdkInternalApi
public class S3EventNotificationMethodToV2 extends Recipe {

private static final MethodMatcher GET_EVENT_TIME = v1EnMethodMatcher("S3EventNotification.S3EventNotificationRecord "
+ "getEventTime(..)");

private static final MethodMatcher GET_EXPIRY_TIME = v1EnMethodMatcher("S3EventNotification.RestoreEventDataEntity "
+ "getLifecycleRestorationExpiryTime(..)");

@Override
public String getDisplayName() {
return "S3 Event Notification method to v2";
}

@Override
public String getDescription() {
return "S3 Event Notification method to v2";
}

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

private static class Visitor extends JavaVisitor<ExecutionContext> {
@Override
public J visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) {
if (GET_EVENT_TIME.matches(method) || GET_EXPIRY_TIME.matches(method)) {
JavaTemplate template = JavaTemplate.builder("new DateTime(#{any(java.time.Instant)}.toEpochMilli())")
.build();
J m = super.visitMethodInvocation(method, ctx);
m = template.apply(getCursor(), ((J.MethodInvocation) m).getCoordinates().replace(), m);
return m;
}
return method;
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public final class S3TransformUtils {
public static final String V1_S3_CLIENT = "com.amazonaws.services.s3.AmazonS3";
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 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 Expand Up @@ -77,6 +78,10 @@ public static MethodMatcher v1S3MethodMatcher(String methodSignature) {
return new MethodMatcher(V1_S3_CLIENT + " " + methodSignature, true);
}

public static MethodMatcher v1EnMethodMatcher(String methodSignature) {
return new MethodMatcher(V1_EN_PKG + methodSignature, true);
}

public static MethodMatcher v2S3MethodMatcher(String methodSignature) {
return new MethodMatcher(V2_S3_CLIENT + " " + methodSignature, true);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ public final class SdkTypeUtils {
CLASSES_TO_SKIP.add(V1_S3_MODEL_PKG + "S3ObjectId");
CLASSES_TO_SKIP.add(V1_S3_MODEL_PKG + "S3ObjectIdBuilder");
CLASSES_TO_SKIP.add(V1_S3_MODEL_PKG + "TagSet");
CLASSES_TO_SKIP.add(V1_S3_MODEL_PKG + "SelectObjectContentEvent");

// S3 Enums with no v2 equivalent
CLASSES_TO_SKIP.add(V1_S3_MODEL_PKG + "GroupGrantee");
Expand Down
Loading
Loading