Skip to content

Commit ad35231

Browse files
authored
Merge pull request #3515 from aws/zoewang/releaseFlexibleChecksumV2
Release support for S3 checksum change.
2 parents 129f56f + 7266fcc commit ad35231

File tree

151 files changed

+6855
-3110
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

151 files changed

+6855
-3110
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"type": "feature",
3+
"category": "Amazon S3",
4+
"contributor": "",
5+
"description": "S3 client behavior is updated to always calculate a checksum by default for operations that support it (such as PutObject or UploadPart), or require it (such as DeleteObjects). The checksum algorithm used by default is CRC32. The S3 client attempts to validate response checksums for all S3 API operations that support checksums. However, if the SDK has not implemented the specified checksum algorithm then this validation is skipped. See [Dev Guide](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/s3-checksums.html) for more information"
6+
}

codegen/pom.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,16 @@
162162
<artifactId>json-utils</artifactId>
163163
<version>${awsjavasdk.version}</version>
164164
</dependency>
165+
<dependency>
166+
<groupId>software.amazon.awssdk</groupId>
167+
<artifactId>checksums</artifactId>
168+
<version>${awsjavasdk.version}</version>
169+
</dependency>
170+
<dependency>
171+
<groupId>software.amazon.awssdk</groupId>
172+
<artifactId>checksums-spi</artifactId>
173+
<version>${awsjavasdk.version}</version>
174+
</dependency>
165175

166176
<dependency>
167177
<artifactId>org.eclipse.jdt.core</artifactId>

codegen/src/main/java/software/amazon/awssdk/codegen/model/config/customization/ServiceConfig.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ public class ServiceConfig {
4949

5050
private boolean hasCrossRegionAccessEnabledProperty = false;
5151

52+
private boolean hasChecksumValidationEnabledProperty = false;
53+
5254
public String getClassName() {
5355
return className;
5456
}
@@ -112,4 +114,12 @@ public boolean hasAccelerateModeEnabledProperty() {
112114
public void setHasAccelerateModeEnabledProperty(boolean hasAccelerateModeEnabledProperty) {
113115
this.hasAccelerateModeEnabledProperty = hasAccelerateModeEnabledProperty;
114116
}
117+
118+
public boolean hasChecksumValidationEnabledProperty() {
119+
return hasChecksumValidationEnabledProperty;
120+
}
121+
122+
public void setHasChecksumValidationEnabledProperty(boolean hasChecksumValidationEnabledProperty) {
123+
this.hasChecksumValidationEnabledProperty = hasChecksumValidationEnabledProperty;
124+
}
115125
}

codegen/src/main/java/software/amazon/awssdk/codegen/poet/PoetUtils.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,5 +108,4 @@ public static JavaFile buildJavaFile(ClassSpec spec) {
108108
spec.staticImports().forEach(i -> i.memberNames().forEach(m -> builder.addStaticImport(i.className(), m)));
109109
return builder.build();
110110
}
111-
112111
}

codegen/src/main/java/software/amazon/awssdk/codegen/poet/builder/BaseClientBuilderClass.java

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
import static javax.lang.model.element.Modifier.FINAL;
1919
import static javax.lang.model.element.Modifier.PRIVATE;
2020
import static javax.lang.model.element.Modifier.PROTECTED;
21+
import static software.amazon.awssdk.codegen.poet.client.traits.HttpChecksumTrait.hasRequestAlgorithmMember;
22+
import static software.amazon.awssdk.codegen.poet.client.traits.HttpChecksumTrait.hasResponseAlgorithms;
2123

2224
import com.squareup.javapoet.ClassName;
2325
import com.squareup.javapoet.CodeBlock;
@@ -59,6 +61,10 @@
5961
import software.amazon.awssdk.codegen.poet.rules.EndpointRulesSpecUtils;
6062
import software.amazon.awssdk.codegen.utils.AuthUtils;
6163
import software.amazon.awssdk.core.SdkPlugin;
64+
import software.amazon.awssdk.core.checksums.RequestChecksumCalculation;
65+
import software.amazon.awssdk.core.checksums.RequestChecksumCalculationResolver;
66+
import software.amazon.awssdk.core.checksums.ResponseChecksumValidation;
67+
import software.amazon.awssdk.core.checksums.ResponseChecksumValidationResolver;
6268
import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption;
6369
import software.amazon.awssdk.core.client.config.SdkClientConfiguration;
6470
import software.amazon.awssdk.core.client.config.SdkClientOption;
@@ -157,6 +163,14 @@ public TypeSpec poetSpec() {
157163
builder.addMethod(authSchemesMethod());
158164
}
159165

166+
if (hasRequestAlgorithmMember(model)) {
167+
builder.addMethod(requestChecksumCalculationMethod());
168+
}
169+
170+
if (hasResponseAlgorithms(model)) {
171+
builder.addMethod(responseChecksumValidationMethod());
172+
}
173+
160174
if (hasClientContextParams()) {
161175
model.getClientContextParams().forEach((n, m) -> {
162176
builder.addMethod(clientContextParamSetter(n, m));
@@ -189,6 +203,14 @@ public TypeSpec poetSpec() {
189203

190204
endpointParamsKnowledgeIndex.resolveAccountIdEndpointModeMethod().ifPresent(builder::addMethod);
191205

206+
if (hasRequestAlgorithmMember(model)) {
207+
builder.addMethod(resolveRequestChecksumCalculationMethod());
208+
}
209+
210+
if (hasResponseAlgorithms(model)) {
211+
builder.addMethod(resolveResponseChecksumValidationMethod());
212+
}
213+
192214
builder.addMethod(validateClientOptionsMethod());
193215

194216
return builder.build();
@@ -487,6 +509,19 @@ private MethodSpec finalizeServiceConfigurationMethod() {
487509
}
488510
}
489511

512+
if (hasRequestAlgorithmMember(model) || hasResponseAlgorithms(model)) {
513+
builder.addStatement("$T clientConfig = config", SdkClientConfiguration.class);
514+
515+
if (hasRequestAlgorithmMember(model)) {
516+
builder.addStatement("builder.lazyOption($T.REQUEST_CHECKSUM_CALCULATION, "
517+
+ "c -> resolveRequestChecksumCalculation(clientConfig))", SdkClientOption.class);
518+
}
519+
if (hasResponseAlgorithms(model)) {
520+
builder.addStatement("builder.lazyOption($T.RESPONSE_CHECKSUM_VALIDATION, "
521+
+ "c -> resolveResponseChecksumValidation(clientConfig))", SdkClientOption.class);
522+
}
523+
}
524+
490525
builder.addStatement("return builder.build()");
491526
return builder.build();
492527
}
@@ -576,6 +611,51 @@ private void mergeServiceConfiguration(MethodSpec.Builder builder, String client
576611
.addCode("}");
577612
}
578613

614+
boolean hasRequestAlgorithmMember = hasRequestAlgorithmMember(model);
615+
boolean hasResponseAlgorithms = hasResponseAlgorithms(model);
616+
if (model.getCustomizationConfig().getServiceConfig().hasChecksumValidationEnabledProperty()
617+
&& (hasRequestAlgorithmMember || hasResponseAlgorithms)) {
618+
builder.addStatement("$T checksumValidationEnabled = serviceConfigBuilder.checksumValidationEnabled()", Boolean.class)
619+
.beginControlFlow("if (checksumValidationEnabled != null)");
620+
if (hasRequestAlgorithmMember) {
621+
builder.addCode("$T.validState(config.option($T.REQUEST_CHECKSUM_CALCULATION) == null, ",
622+
Validate.class, SdkClientOption.class)
623+
.addStatement("\"Checksum behavior has been configured on both $L and the client/global level. Please "
624+
+ "limit checksum behavior configuration to one location.\")", clientConfigClassName);
625+
}
626+
if (hasResponseAlgorithms) {
627+
builder.addCode("$T.validState(config.option($T.RESPONSE_CHECKSUM_VALIDATION) == null, ",
628+
Validate.class, SdkClientOption.class)
629+
.addStatement("\"Checksum behavior has been configured on both $L and the client/global level. Please "
630+
+ "limit checksum behavior configuration to one location.\")", clientConfigClassName);
631+
}
632+
builder.beginControlFlow("if (checksumValidationEnabled)")
633+
.addCode("config = config.toBuilder()");
634+
if (hasRequestAlgorithmMember) {
635+
builder.addCode(".option($T.REQUEST_CHECKSUM_CALCULATION, $T.WHEN_SUPPORTED)",
636+
SdkClientOption.class, RequestChecksumCalculation.class);
637+
}
638+
if (hasResponseAlgorithms) {
639+
builder.addCode(".option($T.RESPONSE_CHECKSUM_VALIDATION, $T.WHEN_SUPPORTED)",
640+
SdkClientOption.class, ResponseChecksumValidation.class);
641+
}
642+
builder.addStatement(".build()")
643+
.nextControlFlow("else")
644+
.addCode("config = config.toBuilder()");
645+
646+
if (hasRequestAlgorithmMember) {
647+
builder.addCode(".option($T.REQUEST_CHECKSUM_CALCULATION, $T.WHEN_REQUIRED)",
648+
SdkClientOption.class, RequestChecksumCalculation.class);
649+
}
650+
if (hasResponseAlgorithms) {
651+
builder.addCode(".option($T.RESPONSE_CHECKSUM_VALIDATION, $T.WHEN_REQUIRED)",
652+
SdkClientOption.class, ResponseChecksumValidation.class);
653+
}
654+
builder.addStatement(".build()")
655+
.endControlFlow()
656+
.endControlFlow();
657+
}
658+
579659
builder.addStatement("$T finalServiceConfig = serviceConfigBuilder.build()", clientConfigClass);
580660

581661
if (model.getCustomizationConfig().getServiceConfig().hasUseArnRegionProperty()) {
@@ -740,6 +820,28 @@ private MethodSpec putAuthSchemeMethod() {
740820
.build();
741821
}
742822

823+
private MethodSpec requestChecksumCalculationMethod() {
824+
return MethodSpec.methodBuilder("requestChecksumCalculation")
825+
.addModifiers(Modifier.PUBLIC)
826+
.returns(TypeVariableName.get("B"))
827+
.addParameter(RequestChecksumCalculation.class, "requestChecksumCalculation")
828+
.addStatement("clientConfiguration.option($T.REQUEST_CHECKSUM_CALCULATION, requestChecksumCalculation)",
829+
SdkClientOption.class)
830+
.addStatement("return thisBuilder()")
831+
.build();
832+
}
833+
834+
private MethodSpec responseChecksumValidationMethod() {
835+
return MethodSpec.methodBuilder("responseChecksumValidation")
836+
.addModifiers(Modifier.PUBLIC)
837+
.returns(TypeVariableName.get("B"))
838+
.addParameter(ResponseChecksumValidation.class, "responseChecksumValidation")
839+
.addStatement("clientConfiguration.option($T.RESPONSE_CHECKSUM_VALIDATION, responseChecksumValidation)",
840+
SdkClientOption.class)
841+
.addStatement("return thisBuilder()")
842+
.build();
843+
}
844+
743845
private MethodSpec clientContextParamSetter(String name, ClientContextParam param) {
744846
String setterName = endpointRulesSpecUtils.paramMethodName(name);
745847
String keyName = model.getNamingStrategy().getEnumValueName(name);
@@ -854,6 +956,50 @@ private MethodSpec internalPluginsMethod() {
854956
return builder.build();
855957
}
856958

959+
private MethodSpec resolveRequestChecksumCalculationMethod() {
960+
961+
MethodSpec.Builder builder = MethodSpec.methodBuilder("resolveRequestChecksumCalculation")
962+
.addModifiers(PRIVATE)
963+
.addParameter(SdkClientConfiguration.class, "config")
964+
.returns(RequestChecksumCalculation.class);
965+
966+
builder.addStatement("$T configuredChecksumCalculation = config.option($T.REQUEST_CHECKSUM_CALCULATION)",
967+
RequestChecksumCalculation.class, SdkClientOption.class);
968+
969+
builder.beginControlFlow("if (configuredChecksumCalculation == null)");
970+
builder.addCode("configuredChecksumCalculation = $T.create()", RequestChecksumCalculationResolver.class);
971+
builder.addCode(".profileFile(config.option($T.PROFILE_FILE_SUPPLIER))", SdkClientOption.class);
972+
builder.addCode(".profileName(config.option($T.PROFILE_NAME))", SdkClientOption.class);
973+
builder.addCode(".defaultChecksumCalculation($T.WHEN_SUPPORTED)", RequestChecksumCalculation.class);
974+
builder.addStatement(".resolve()");
975+
builder.endControlFlow();
976+
977+
builder.addStatement("return configuredChecksumCalculation");
978+
return builder.build();
979+
}
980+
981+
private MethodSpec resolveResponseChecksumValidationMethod() {
982+
983+
MethodSpec.Builder builder = MethodSpec.methodBuilder("resolveResponseChecksumValidation")
984+
.addModifiers(PRIVATE)
985+
.addParameter(SdkClientConfiguration.class, "config")
986+
.returns(ResponseChecksumValidation.class);
987+
988+
builder.addStatement("$T configuredChecksumValidation = config.option($T.RESPONSE_CHECKSUM_VALIDATION)",
989+
ResponseChecksumValidation.class, SdkClientOption.class);
990+
991+
builder.beginControlFlow("if (configuredChecksumValidation == null)");
992+
builder.addCode("configuredChecksumValidation = $T.create()", ResponseChecksumValidationResolver.class);
993+
builder.addCode(".profileFile(config.option($T.PROFILE_FILE_SUPPLIER))", SdkClientOption.class);
994+
builder.addCode(".profileName(config.option($T.PROFILE_NAME))", SdkClientOption.class);
995+
builder.addCode(".defaultChecksumValidation($T.WHEN_SUPPORTED)", ResponseChecksumValidation.class);
996+
builder.addStatement(".resolve()");
997+
builder.endControlFlow();
998+
999+
builder.addStatement("return configuredChecksumValidation");
1000+
return builder.build();
1001+
}
1002+
8571003
private String internalPluginClass(String internalPlugin) {
8581004
int openParenthesisIndex = internalPlugin.indexOf('(');
8591005
if (openParenthesisIndex == -1) {

codegen/src/main/java/software/amazon/awssdk/codegen/poet/builder/BaseClientBuilderInterface.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
import software.amazon.awssdk.codegen.poet.rules.EndpointParamsKnowledgeIndex;
4040
import software.amazon.awssdk.codegen.poet.rules.EndpointRulesSpecUtils;
4141
import software.amazon.awssdk.codegen.utils.AuthUtils;
42+
import software.amazon.awssdk.core.checksums.RequestChecksumCalculation;
43+
import software.amazon.awssdk.core.checksums.ResponseChecksumValidation;
4244
import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption;
4345
import software.amazon.awssdk.identity.spi.IdentityProvider;
4446
import software.amazon.awssdk.identity.spi.TokenIdentity;
@@ -106,6 +108,14 @@ public TypeSpec poetSpec() {
106108
builder.addMethod(tokenIdentityProviderMethod());
107109
}
108110

111+
if (hasRequestAlgorithmMember(model)) {
112+
builder.addMethod(requestChecksumCalculationMethod());
113+
}
114+
115+
if (hasResponseAlgorithms(model)) {
116+
builder.addMethod(responseChecksumValidationMethod());
117+
}
118+
109119
return builder.build();
110120
}
111121

@@ -183,6 +193,26 @@ private MethodSpec authSchemeProviderMethod() {
183193
.build();
184194
}
185195

196+
private MethodSpec requestChecksumCalculationMethod() {
197+
return MethodSpec.methodBuilder("requestChecksumCalculation")
198+
.addModifiers(Modifier.PUBLIC, Modifier.DEFAULT)
199+
.addParameter(RequestChecksumCalculation.class, "requestChecksumCalculation")
200+
.addJavadoc("Configures the client behavior for request checksum calculation.")
201+
.returns(TypeVariableName.get("B"))
202+
.addStatement("throw new $T()", UnsupportedOperationException.class)
203+
.build();
204+
}
205+
206+
private MethodSpec responseChecksumValidationMethod() {
207+
return MethodSpec.methodBuilder("responseChecksumValidation")
208+
.addModifiers(Modifier.PUBLIC, Modifier.DEFAULT)
209+
.addParameter(ResponseChecksumValidation.class, "responseChecksumValidation")
210+
.addJavadoc("Configures the client behavior for response checksum validation.")
211+
.returns(TypeVariableName.get("B"))
212+
.addStatement("throw new $T()", UnsupportedOperationException.class)
213+
.build();
214+
}
215+
186216
private MethodSpec clientContextParamSetter(String name, ClientContextParam param) {
187217
String setterName = Utils.unCapitalize(CodegenNamingUtils.pascalCase(name));
188218
TypeName type = endpointRulesSpecUtils.toJavaType(param.getType());
@@ -255,4 +285,16 @@ private boolean hasSdkClientContextParams() {
255285
&& model.getCustomizationConfig().getCustomClientContextParams() != null
256286
&& !model.getCustomizationConfig().getCustomClientContextParams().isEmpty();
257287
}
288+
289+
private boolean hasRequestAlgorithmMember(IntermediateModel model) {
290+
return model.getOperations().values().stream()
291+
.anyMatch(opModel -> opModel.getHttpChecksum() != null
292+
&& opModel.getHttpChecksum().getRequestAlgorithmMember() != null);
293+
}
294+
295+
private boolean hasResponseAlgorithms(IntermediateModel model) {
296+
return model.getOperations().values().stream()
297+
.anyMatch(opModel -> opModel.getHttpChecksum() != null
298+
&& opModel.getHttpChecksum().getResponseAlgorithms() != null);
299+
}
258300
}

0 commit comments

Comments
 (0)