diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/builder/AsyncClientBuilderClass.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/builder/AsyncClientBuilderClass.java index d26b113a5221..25bc9ad11671 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/builder/AsyncClientBuilderClass.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/builder/AsyncClientBuilderClass.java @@ -21,7 +21,6 @@ import com.squareup.javapoet.ParameterizedTypeName; import com.squareup.javapoet.TypeSpec; import com.squareup.javapoet.WildcardTypeName; -import java.net.URI; import javax.lang.model.element.Modifier; import software.amazon.awssdk.annotations.SdkInternalApi; import software.amazon.awssdk.awscore.client.config.AwsClientOption; @@ -34,7 +33,6 @@ import software.amazon.awssdk.codegen.utils.AuthUtils; import software.amazon.awssdk.core.client.config.SdkClientConfiguration; import software.amazon.awssdk.core.client.config.SdkClientOption; -import software.amazon.awssdk.endpoints.EndpointProvider; import software.amazon.awssdk.identity.spi.IdentityProvider; import software.amazon.awssdk.identity.spi.TokenIdentity; @@ -91,7 +89,7 @@ public TypeSpec poetSpec() { } builder.addMethod(buildClientMethod()); - builder.addMethod(initializeServiceClientConfigMethod()); + builder.addMethod(SyncClientBuilderClass.initializeServiceClientConfigMethod(serviceConfigClassName)); return builder.build(); } @@ -194,29 +192,6 @@ private MethodSpec multipartConfigMethods(MultipartCustomization multipartCustom .build(); } - private MethodSpec initializeServiceClientConfigMethod() { - return MethodSpec.methodBuilder("initializeServiceClientConfig").addModifiers(Modifier.PRIVATE) - .addParameter(SdkClientConfiguration.class, "clientConfig") - .returns(serviceConfigClassName) - .addStatement("$T endpointOverride = null", URI.class) - .addStatement("$T endpointProvider = clientConfig.option($T.ENDPOINT_PROVIDER)", - EndpointProvider.class, - SdkClientOption.class) - .addCode("if (clientConfig.option($T.ENDPOINT_OVERRIDDEN) != null" - + "&& $T.TRUE.equals(clientConfig.option($T.ENDPOINT_OVERRIDDEN))) {" - + "endpointOverride = clientConfig.option($T.ENDPOINT);" - + "}", - SdkClientOption.class, Boolean.class, SdkClientOption.class, SdkClientOption.class) - .addStatement("return $T.builder()" - + ".overrideConfiguration(overrideConfiguration())" - + ".region(clientConfig.option($T.AWS_REGION))" - + ".endpointOverride(endpointOverride)" - + ".endpointProvider(endpointProvider)" - + ".build()", - serviceConfigClassName, AwsClientOption.class) - .build(); - } - @Override public ClassName className() { return builderClassName; diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/builder/SyncClientBuilderClass.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/builder/SyncClientBuilderClass.java index cb7589dab28c..1582b90f6c1b 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/builder/SyncClientBuilderClass.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/builder/SyncClientBuilderClass.java @@ -32,7 +32,6 @@ import software.amazon.awssdk.codegen.utils.AuthUtils; import software.amazon.awssdk.core.client.config.SdkClientConfiguration; import software.amazon.awssdk.core.client.config.SdkClientOption; -import software.amazon.awssdk.endpoints.EndpointProvider; import software.amazon.awssdk.identity.spi.IdentityProvider; import software.amazon.awssdk.identity.spi.TokenIdentity; @@ -61,12 +60,12 @@ public SyncClientBuilderClass(IntermediateModel model) { @Override public TypeSpec poetSpec() { TypeSpec.Builder builder = - PoetUtils.createClassBuilder(builderClassName) - .addAnnotation(SdkInternalApi.class) - .addModifiers(Modifier.FINAL) - .superclass(ParameterizedTypeName.get(builderBaseClassName, builderInterfaceName, clientInterfaceName)) - .addSuperinterface(builderInterfaceName) - .addJavadoc("Internal implementation of {@link $T}.", builderInterfaceName); + PoetUtils.createClassBuilder(builderClassName) + .addAnnotation(SdkInternalApi.class) + .addModifiers(Modifier.FINAL) + .superclass(ParameterizedTypeName.get(builderBaseClassName, builderInterfaceName, clientInterfaceName)) + .addSuperinterface(builderInterfaceName) + .addJavadoc("Internal implementation of {@link $T}.", builderInterfaceName); if (model.getEndpointOperation().isPresent()) { builder.addMethod(endpointDiscoveryEnabled()); @@ -83,7 +82,7 @@ public TypeSpec poetSpec() { } builder.addMethod(buildClientMethod()); - builder.addMethod(initializeServiceClientConfigMethod()); + builder.addMethod(initializeServiceClientConfigMethod(serviceConfigClassName)); return builder.build(); } @@ -126,15 +125,15 @@ private MethodSpec endpointProviderMethod() { private MethodSpec buildClientMethod() { MethodSpec.Builder builder = MethodSpec.methodBuilder("buildClient") - .addAnnotation(Override.class) - .addModifiers(Modifier.PROTECTED, Modifier.FINAL) - .returns(clientInterfaceName) - .addStatement("$T clientConfiguration = super.syncClientConfiguration()", - SdkClientConfiguration.class) - .addStatement("this.validateClientOptions(clientConfiguration)") - .addStatement("$T serviceClientConfiguration = initializeServiceClientConfig" - + "(clientConfiguration)", - serviceConfigClassName); + .addAnnotation(Override.class) + .addModifiers(Modifier.PROTECTED, Modifier.FINAL) + .returns(clientInterfaceName) + .addStatement("$T clientConfiguration = super.syncClientConfiguration()", + SdkClientConfiguration.class) + .addStatement("this.validateClientOptions(clientConfiguration)") + .addStatement("$T serviceClientConfiguration = initializeServiceClientConfig" + + "(clientConfiguration)", + serviceConfigClassName); builder.addStatement("$1T client = new $2T(serviceClientConfiguration, clientConfiguration)", clientInterfaceName, clientClassName); @@ -160,26 +159,23 @@ private MethodSpec tokenProviderMethodImpl() { .build(); } - private MethodSpec initializeServiceClientConfigMethod() { + // TODO(sra-plugins) Move this method to a commons class or move it to the base class + public static MethodSpec initializeServiceClientConfigMethod(ClassName serviceConfigClassName) { return MethodSpec.methodBuilder("initializeServiceClientConfig").addModifiers(Modifier.PRIVATE) .addParameter(SdkClientConfiguration.class, "clientConfig") .returns(serviceConfigClassName) .addStatement("$T endpointOverride = null", URI.class) - .addStatement("$T endpointProvider = clientConfig.option($T.ENDPOINT_PROVIDER)", - EndpointProvider.class, - SdkClientOption.class) - .addCode("if (clientConfig.option($T.ENDPOINT_OVERRIDDEN) != null" - + "&& $T.TRUE.equals(clientConfig.option($T.ENDPOINT_OVERRIDDEN))) {" - + "endpointOverride = clientConfig.option($T.ENDPOINT);" - + "}", - SdkClientOption.class, Boolean.class, SdkClientOption.class, SdkClientOption.class) + .beginControlFlow("if ($T.TRUE.equals(clientConfig.option($T.ENDPOINT_OVERRIDDEN)))", Boolean.class, + SdkClientOption.class) + .addStatement("endpointOverride = clientConfig.option($T.ENDPOINT)", SdkClientOption.class) + .endControlFlow() .addStatement("return $T.builder()" + ".overrideConfiguration(overrideConfiguration())" + ".region(clientConfig.option($T.AWS_REGION))" + ".endpointOverride(endpointOverride)" - + ".endpointProvider(endpointProvider)" + + ".endpointProvider(clientConfig.option($T.ENDPOINT_PROVIDER))" + ".build()", - serviceConfigClassName, AwsClientOption.class) + serviceConfigClassName, AwsClientOption.class, SdkClientOption.class) .build(); } diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/model/ServiceClientConfigurationClass.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/model/ServiceClientConfigurationClass.java index 8d872211ea85..aa58f50223df 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/model/ServiceClientConfigurationClass.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/model/ServiceClientConfigurationClass.java @@ -23,24 +23,43 @@ import com.squareup.javapoet.ClassName; import com.squareup.javapoet.MethodSpec; +import com.squareup.javapoet.ParameterizedTypeName; +import com.squareup.javapoet.TypeName; import com.squareup.javapoet.TypeSpec; +import com.squareup.javapoet.WildcardTypeName; import java.net.URI; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import software.amazon.awssdk.annotations.SdkPublicApi; import software.amazon.awssdk.awscore.AwsServiceClientConfiguration; +import software.amazon.awssdk.awscore.client.config.AwsClientOption; import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel; import software.amazon.awssdk.codegen.poet.ClassSpec; import software.amazon.awssdk.codegen.poet.PoetUtils; +import software.amazon.awssdk.codegen.poet.auth.scheme.AuthSchemeSpecUtils; +import software.amazon.awssdk.core.client.config.ClientOption; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +import software.amazon.awssdk.core.client.config.SdkClientConfiguration; +import software.amazon.awssdk.core.client.config.SdkClientOption; +import software.amazon.awssdk.core.internal.SdkInternalAdvancedClientOption; import software.amazon.awssdk.endpoints.EndpointProvider; +import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeProvider; +import software.amazon.awssdk.identity.spi.AwsCredentialsIdentity; +import software.amazon.awssdk.identity.spi.IdentityProvider; import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.utils.Validate; public class ServiceClientConfigurationClass implements ClassSpec { private final ClassName defaultClientMetadataClassName; + private final AuthSchemeSpecUtils authSchemeSpecUtils; public ServiceClientConfigurationClass(IntermediateModel model) { String basePackage = model.getMetadata().getFullClientPackageName(); String serviceId = model.getMetadata().getServiceName(); this.defaultClientMetadataClassName = ClassName.get(basePackage, serviceId + "ServiceClientConfiguration"); + this.authSchemeSpecUtils = new AuthSchemeSpecUtils(model); + } @Override @@ -51,6 +70,7 @@ public TypeSpec poetSpec() { AwsServiceClientConfiguration.class) .addMethod(constructor()) .addMethod(builderMethod()) + .addMethod(builderFromSdkClientConfiguration()) .addModifiers(PUBLIC, FINAL) .addAnnotation(SdkPublicApi.class) .addType(builderInterfaceSpec()) @@ -63,7 +83,7 @@ public ClassName className() { return defaultClientMetadataClassName; } - public MethodSpec constructor() { + private MethodSpec constructor() { return MethodSpec.constructorBuilder() .addModifiers(PRIVATE) .addParameter(className().nestedClass("Builder"), "builder") @@ -71,7 +91,7 @@ public MethodSpec constructor() { .build(); } - public MethodSpec builderMethod() { + private MethodSpec builderMethod() { return MethodSpec.methodBuilder("builder") .addModifiers(PUBLIC, STATIC) .addStatement("return new BuilderImpl()") @@ -80,98 +100,283 @@ public MethodSpec builderMethod() { .build(); } + private MethodSpec builderFromSdkClientConfiguration() { + return MethodSpec.methodBuilder("builder") + .addModifiers(PUBLIC, STATIC) + .addParameter(SdkClientConfiguration.Builder.class, "builder") + .addStatement("return new BuilderImpl(builder)") + .returns(className().nestedClass("Builder")) + .addJavadoc("") + .build(); + } + private TypeSpec builderInterfaceSpec() { - return TypeSpec.interfaceBuilder("Builder") - .addModifiers(PUBLIC) - .addSuperinterface(ClassName.get(AwsServiceClientConfiguration.class).nestedClass("Builder")) - .addJavadoc("A builder for creating a {@link $T}", className()) - .addMethod(MethodSpec.methodBuilder("build") - .addAnnotation(Override.class) - .addModifiers(PUBLIC, ABSTRACT) - .returns(className()) - .build()) - .addMethod(MethodSpec.methodBuilder("region") - .addAnnotation(Override.class) - .addModifiers(PUBLIC, ABSTRACT) - .addParameter(Region.class, "region") - .returns(className().nestedClass("Builder")) - .addJavadoc("Configure the region") - .build()) - .addMethod(MethodSpec.methodBuilder("endpointOverride") - .addAnnotation(Override.class) - .addModifiers(PUBLIC, ABSTRACT) - .addParameter(URI.class, "endpointOverride") - .returns(className().nestedClass("Builder")) - .addJavadoc("Configure the endpointOverride") - .build()) - .addMethod(MethodSpec.methodBuilder("overrideConfiguration") - .addAnnotation(Override.class) - .addModifiers(PUBLIC, ABSTRACT) - .addParameter(ClientOverrideConfiguration.class, "clientOverrideConfiguration") - .returns(className().nestedClass("Builder")) - .addJavadoc("Configure the client override configuration") - .build()) - .addMethod(MethodSpec.methodBuilder("endpointProvider") - .addAnnotation(Override.class) - .addModifiers(PUBLIC, ABSTRACT) - .addParameter(EndpointProvider.class, "endpointProvider") - .returns(className().nestedClass("Builder")) - .addJavadoc("Configure the endpointProvider") - .build()) - .build(); + TypeSpec.Builder builder = TypeSpec.interfaceBuilder("Builder") + .addModifiers(PUBLIC) + .addSuperinterface(ClassName.get(AwsServiceClientConfiguration.class).nestedClass( + "Builder")) + .addJavadoc("A builder for creating a {@link $T}", className()); + for (Field field : serviceClientConfigurationFields()) { + builder.addMethod(baseSetterForField(field) + .addModifiers(ABSTRACT) + .build()); + builder.addMethod(baseGetterForField(field) + .addModifiers(ABSTRACT) + .build()); + } + builder.addMethod(MethodSpec.methodBuilder("build") + .addAnnotation(Override.class) + .addModifiers(PUBLIC, ABSTRACT) + .returns(className()) + .build()); + return builder.build(); } private TypeSpec builderImplSpec() { - return TypeSpec.classBuilder("BuilderImpl") - .addModifiers(PRIVATE, STATIC, FINAL) - .addSuperinterface(className().nestedClass("Builder")) - .superclass(ClassName.get(AwsServiceClientConfiguration.class).nestedClass("BuilderImpl")) - .addMethod(MethodSpec.constructorBuilder() - .addModifiers(PRIVATE) - .build()) - .addMethod(MethodSpec.constructorBuilder() - .addModifiers(PRIVATE) - .addParameter(className(), "serviceClientConfiguration") - .addStatement("super(serviceClientConfiguration)") - .build()) - .addMethod(MethodSpec.methodBuilder("region") - .addAnnotation(Override.class) - .addModifiers(PUBLIC) - .addParameter(Region.class, "region") - .returns(className().nestedClass("Builder")) - .addStatement("this.region = region") - .addStatement("return this") - .build()) - .addMethod(MethodSpec.methodBuilder("overrideConfiguration") - .addAnnotation(Override.class) - .addModifiers(PUBLIC) - .addParameter(ClientOverrideConfiguration.class, "clientOverrideConfiguration") - .returns(className().nestedClass("Builder")) - .addStatement("this.overrideConfiguration = clientOverrideConfiguration") - .addStatement("return this") - .build()) - .addMethod(MethodSpec.methodBuilder("endpointOverride") - .addAnnotation(Override.class) - .addModifiers(PUBLIC) - .addParameter(URI.class, "endpointOverride") - .returns(className().nestedClass("Builder")) - .addStatement("this.endpointOverride = endpointOverride") - .addStatement("return this") - .build()) - .addMethod(MethodSpec.methodBuilder("endpointProvider") - .addAnnotation(Override.class) - .addModifiers(PUBLIC) - .addParameter(EndpointProvider.class, "endpointProvider") - .returns(className().nestedClass("Builder")) - .addStatement("this.endpointProvider = endpointProvider") - .addStatement("return this") - .build()) - .addMethod(MethodSpec.methodBuilder("build") - .addAnnotation(Override.class) - .addModifiers(PUBLIC) - .returns(className()) - .addStatement("return new $T(this)", className()) - .build()) - .build(); + TypeSpec.Builder builder = TypeSpec.classBuilder("BuilderImpl") + .addModifiers(PRIVATE, STATIC, FINAL) + .addSuperinterface(className().nestedClass("Builder")); + + builder.addField(SdkClientConfiguration.Builder.class, "builder", PRIVATE, FINAL); + builder.addMethod(MethodSpec.constructorBuilder() + .addModifiers(PRIVATE) + .addStatement("this.builder = $T.builder()", SdkClientConfiguration.class) + .build()); + + builder.addMethod(MethodSpec.constructorBuilder() + .addModifiers(PRIVATE) + .addParameter(SdkClientConfiguration.Builder.class, "builder") + .addStatement("this.builder = builder", SdkClientConfiguration.class) + .build()); + + for (Field field : serviceClientConfigurationFields()) { + addLocalFieldIfNeeded(field, builder); + builder.addMethod(setterForField(field)); + builder.addMethod(getterForField(field)); + } + + builder.addMethod(MethodSpec.methodBuilder("build") + .addAnnotation(Override.class) + .addModifiers(PUBLIC) + .returns(className()) + .addStatement("return new $T(this)", className()) + .build()); + + builder.addMethod(MethodSpec.methodBuilder("buildSdkClientConfiguration") + .addModifiers(PUBLIC) + .returns(SdkClientConfiguration.class) + .beginControlFlow("if (overrideConfiguration != null)") + .addStatement("overrideConfiguration.addOverridesToConfiguration(builder)") + .endControlFlow() + .addStatement("return builder.build()") + .build()); + return builder.build(); + } + + private void addLocalFieldIfNeeded(Field field, TypeSpec.Builder builder) { + if (field.optionClass == null) { + builder.addField(field.type, field.name, PRIVATE); + } + } + + private MethodSpec setterForField(Field field) { + MethodSpec.Builder builder = baseSetterForField(field); + if (!field.isInherited) { + builder.addAnnotation(Override.class); + } + if (field.optionClass == null) { + return builder.addStatement("this.$1L = $1L", field.name) + .addStatement("return this") + .build(); + + } + return builder.addStatement("builder.option($T.$L, $L)", + field.optionClass, field.optionName, field.name) + .addStatement("return this") + .build(); + } + + private MethodSpec.Builder baseSetterForField(Field field) { + MethodSpec.Builder builder = MethodSpec.methodBuilder(field.name) + .addModifiers(PUBLIC) + .addParameter(field.type, field.name) + .addJavadoc("Sets the value for " + field.doc) + .returns(className().nestedClass("Builder")); + if (field.isInherited) { + builder.addAnnotation(Override.class); + } + return builder; + } + + private MethodSpec getterForField(Field field) { + MethodSpec.Builder builder = baseGetterForField(field); + if (!field.isInherited) { + builder.addAnnotation(Override.class); + } + if (field.optionClass == null) { + return builder.addStatement("return $L", field.name) + .build(); + } + if (field.baseType != null) { + return builder.addStatement("$T result = builder.option($T.$L)", + field.baseType, field.optionClass, field.optionName) + .beginControlFlow("if (result == null)") + .addStatement("return null") + .endControlFlow() + .addStatement("return $T.isInstanceOf($T.class, result, $S + $T.class.getSimpleName())", + Validate.class, field.type, + "Expected an instance of ", field.type) + .build(); + + } + return builder.addStatement("return builder.option($T.$L)", field.optionClass, field.optionName) + .build(); + } + + private MethodSpec.Builder baseGetterForField(Field field) { + MethodSpec.Builder builder = MethodSpec.methodBuilder(field.name) + .addModifiers(PUBLIC) + .addJavadoc("Gets the value for " + field.doc) + .returns(field.type); + if (field.isInherited) { + builder.addAnnotation(Override.class); + } + return builder; + } + + + /** + * Returns the list of fields present in the service client configuration class with its corresponding {@link ClientOption} + * mapping to the {@link SdkClientConfiguration} class. + */ + private List serviceClientConfigurationFields() { + List fields = new ArrayList<>(baseServiceClientConfigurationFields()); + fields.add(Field.builder() + .name("authSchemeProvider") + .type(authSchemeSpecUtils.providerInterfaceName()) + .doc("auth scheme provider") + .optionClass(SdkClientOption.class) + .optionName("AUTH_SCHEME_PROVIDER") + .isInherited(false) + .baseType(ClassName.get(AuthSchemeProvider.class)) + .build()); + return fields; + } + + private static List baseServiceClientConfigurationFields() { + return Arrays.asList( + Field.builder() + .doc("client override configuration") + .name("overrideConfiguration") + .type(ClientOverrideConfiguration.class) + .build(), + Field.builder() + .doc("AWS region") + .name("region") + .type(Region.class) + .optionClass(AwsClientOption.class) + .optionName("AWS_REGION") + .build(), + Field.builder() + .doc("endpoint override") + .name("endpointOverride") + .type(URI.class) + .optionClass(SdkInternalAdvancedClientOption.class) + .optionName("ENDPOINT_OVERRIDE_VALUE") + .build(), + Field.builder() + .name("endpointProvider") + .type(EndpointProvider.class) + .doc("endpoint provider") + .optionClass(SdkClientOption.class) + .optionName("ENDPOINT_PROVIDER") + .build(), + Field.builder() + .name("credentialsProvider") + .type(ParameterizedTypeName.get(ClassName.get(IdentityProvider.class), + WildcardTypeName.subtypeOf(AwsCredentialsIdentity.class))) + .doc("credentials provider") + .optionClass(AwsClientOption.class) + .optionName("CREDENTIALS_IDENTITY_PROVIDER") + .build() + ); + } + + static class Field { + private final String name; + private final TypeName type; + private final Class optionClass; + private final String optionName; + private final String doc; + private final boolean isInherited; + private final TypeName baseType; + + Field(Builder builder) { + this.name = Validate.paramNotNull(builder.name, "name"); + this.type = Validate.paramNotNull(builder.type, "type"); + this.doc = Validate.paramNotNull(builder.doc, "doc"); + this.optionClass = builder.optionClass; + this.optionName = builder.optionName; + this.isInherited = builder.isInherited; + this.baseType = builder.baseType; + } + + public static Builder builder() { + return new Builder(); + } + + static class Builder { + private String name; + private TypeName type; + private String doc; + private Class optionClass; + private String optionName; + private boolean isInherited = true; + private TypeName baseType; + + public Field.Builder name(String name) { + this.name = name; + return this; + } + + public Field.Builder type(Class type) { + this.type = ClassName.get(type); + return this; + } + + public Field.Builder type(TypeName type) { + this.type = type; + return this; + } + + public Field.Builder doc(String doc) { + this.doc = doc; + return this; + } + + public Field.Builder optionClass(Class optionClass) { + this.optionClass = optionClass; + return this; + } + + public Field.Builder optionName(String optionName) { + this.optionName = optionName; + return this; + } + + public Field.Builder isInherited(boolean isInherited) { + this.isInherited = isInherited; + return this; + } + + public Field.Builder baseType(TypeName baseType) { + this.baseType = baseType; + return this; + } + + public Field build() { + return new Field(this); + } + } } } diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-async-client-builder-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-async-client-builder-class.java index 637de77a8ee3..668712af4ae4 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-async-client-builder-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-async-client-builder-class.java @@ -6,7 +6,6 @@ import software.amazon.awssdk.awscore.client.config.AwsClientOption; import software.amazon.awssdk.core.client.config.SdkClientConfiguration; import software.amazon.awssdk.core.client.config.SdkClientOption; -import software.amazon.awssdk.endpoints.EndpointProvider; import software.amazon.awssdk.identity.spi.IdentityProvider; import software.amazon.awssdk.identity.spi.TokenIdentity; import software.amazon.awssdk.services.json.endpoints.JsonEndpointProvider; @@ -17,7 +16,7 @@ @Generated("software.amazon.awssdk:codegen") @SdkInternalApi final class DefaultJsonAsyncClientBuilder extends DefaultJsonBaseClientBuilder implements - JsonAsyncClientBuilder { + JsonAsyncClientBuilder { @Override public DefaultJsonAsyncClientBuilder endpointProvider(JsonEndpointProvider endpointProvider) { clientConfiguration.option(SdkClientOption.ENDPOINT_PROVIDER, endpointProvider); @@ -41,13 +40,11 @@ protected final JsonAsyncClient buildClient() { private JsonServiceClientConfiguration initializeServiceClientConfig(SdkClientConfiguration clientConfig) { URI endpointOverride = null; - EndpointProvider endpointProvider = clientConfig.option(SdkClientOption.ENDPOINT_PROVIDER); - if (clientConfig.option(SdkClientOption.ENDPOINT_OVERRIDDEN) != null - && Boolean.TRUE.equals(clientConfig.option(SdkClientOption.ENDPOINT_OVERRIDDEN))) { + if (Boolean.TRUE.equals(clientConfig.option(SdkClientOption.ENDPOINT_OVERRIDDEN))) { endpointOverride = clientConfig.option(SdkClientOption.ENDPOINT); } return JsonServiceClientConfiguration.builder().overrideConfiguration(overrideConfiguration()) - .region(clientConfig.option(AwsClientOption.AWS_REGION)).endpointOverride(endpointOverride) - .endpointProvider(endpointProvider).build(); + .region(clientConfig.option(AwsClientOption.AWS_REGION)).endpointOverride(endpointOverride) + .endpointProvider(clientConfig.option(SdkClientOption.ENDPOINT_PROVIDER)).build(); } } diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-composed-async-client-builder-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-composed-async-client-builder-class.java index cfea00a1e18d..210c9dce33de 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-composed-async-client-builder-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-composed-async-client-builder-class.java @@ -6,7 +6,6 @@ import software.amazon.awssdk.awscore.client.config.AwsClientOption; import software.amazon.awssdk.core.client.config.SdkClientConfiguration; import software.amazon.awssdk.core.client.config.SdkClientOption; -import software.amazon.awssdk.endpoints.EndpointProvider; import software.amazon.awssdk.identity.spi.IdentityProvider; import software.amazon.awssdk.identity.spi.TokenIdentity; import software.amazon.awssdk.services.builder.AsyncClientDecorator; @@ -42,13 +41,11 @@ protected final JsonAsyncClient buildClient() { private JsonServiceClientConfiguration initializeServiceClientConfig(SdkClientConfiguration clientConfig) { URI endpointOverride = null; - EndpointProvider endpointProvider = clientConfig.option(SdkClientOption.ENDPOINT_PROVIDER); - if (clientConfig.option(SdkClientOption.ENDPOINT_OVERRIDDEN) != null - && Boolean.TRUE.equals(clientConfig.option(SdkClientOption.ENDPOINT_OVERRIDDEN))) { + if (Boolean.TRUE.equals(clientConfig.option(SdkClientOption.ENDPOINT_OVERRIDDEN))) { endpointOverride = clientConfig.option(SdkClientOption.ENDPOINT); } return JsonServiceClientConfiguration.builder().overrideConfiguration(overrideConfiguration()) .region(clientConfig.option(AwsClientOption.AWS_REGION)).endpointOverride(endpointOverride) - .endpointProvider(endpointProvider).build(); + .endpointProvider(clientConfig.option(SdkClientOption.ENDPOINT_PROVIDER)).build(); } } diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-composed-sync-client-builder-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-composed-sync-client-builder-class.java index e708a4684491..1c73c05fc729 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-composed-sync-client-builder-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-composed-sync-client-builder-class.java @@ -6,7 +6,6 @@ import software.amazon.awssdk.awscore.client.config.AwsClientOption; import software.amazon.awssdk.core.client.config.SdkClientConfiguration; import software.amazon.awssdk.core.client.config.SdkClientOption; -import software.amazon.awssdk.endpoints.EndpointProvider; import software.amazon.awssdk.identity.spi.IdentityProvider; import software.amazon.awssdk.identity.spi.TokenIdentity; import software.amazon.awssdk.services.builder.SyncClientDecorator; @@ -42,13 +41,11 @@ protected final JsonClient buildClient() { private JsonServiceClientConfiguration initializeServiceClientConfig(SdkClientConfiguration clientConfig) { URI endpointOverride = null; - EndpointProvider endpointProvider = clientConfig.option(SdkClientOption.ENDPOINT_PROVIDER); - if (clientConfig.option(SdkClientOption.ENDPOINT_OVERRIDDEN) != null - && Boolean.TRUE.equals(clientConfig.option(SdkClientOption.ENDPOINT_OVERRIDDEN))) { + if (Boolean.TRUE.equals(clientConfig.option(SdkClientOption.ENDPOINT_OVERRIDDEN))) { endpointOverride = clientConfig.option(SdkClientOption.ENDPOINT); } return JsonServiceClientConfiguration.builder().overrideConfiguration(overrideConfiguration()) .region(clientConfig.option(AwsClientOption.AWS_REGION)).endpointOverride(endpointOverride) - .endpointProvider(endpointProvider).build(); + .endpointProvider(clientConfig.option(SdkClientOption.ENDPOINT_PROVIDER)).build(); } } diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-sync-client-builder-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-sync-client-builder-class.java index 1e90166018f8..f5e86474a8bd 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-sync-client-builder-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-sync-client-builder-class.java @@ -6,7 +6,6 @@ import software.amazon.awssdk.awscore.client.config.AwsClientOption; import software.amazon.awssdk.core.client.config.SdkClientConfiguration; import software.amazon.awssdk.core.client.config.SdkClientOption; -import software.amazon.awssdk.endpoints.EndpointProvider; import software.amazon.awssdk.identity.spi.IdentityProvider; import software.amazon.awssdk.identity.spi.TokenIdentity; import software.amazon.awssdk.services.json.endpoints.JsonEndpointProvider; @@ -17,7 +16,7 @@ @Generated("software.amazon.awssdk:codegen") @SdkInternalApi final class DefaultJsonClientBuilder extends DefaultJsonBaseClientBuilder implements - JsonClientBuilder { + JsonClientBuilder { @Override public DefaultJsonClientBuilder endpointProvider(JsonEndpointProvider endpointProvider) { clientConfiguration.option(SdkClientOption.ENDPOINT_PROVIDER, endpointProvider); @@ -41,13 +40,11 @@ protected final JsonClient buildClient() { private JsonServiceClientConfiguration initializeServiceClientConfig(SdkClientConfiguration clientConfig) { URI endpointOverride = null; - EndpointProvider endpointProvider = clientConfig.option(SdkClientOption.ENDPOINT_PROVIDER); - if (clientConfig.option(SdkClientOption.ENDPOINT_OVERRIDDEN) != null - && Boolean.TRUE.equals(clientConfig.option(SdkClientOption.ENDPOINT_OVERRIDDEN))) { + if (Boolean.TRUE.equals(clientConfig.option(SdkClientOption.ENDPOINT_OVERRIDDEN))) { endpointOverride = clientConfig.option(SdkClientOption.ENDPOINT); } return JsonServiceClientConfiguration.builder().overrideConfiguration(overrideConfiguration()) - .region(clientConfig.option(AwsClientOption.AWS_REGION)).endpointOverride(endpointOverride) - .endpointProvider(endpointProvider).build(); + .region(clientConfig.option(AwsClientOption.AWS_REGION)).endpointOverride(endpointOverride) + .endpointProvider(clientConfig.option(SdkClientOption.ENDPOINT_PROVIDER)).build(); } } diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/model/serviceclientconfiguration.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/model/serviceclientconfiguration.java index 572604798a8b..4f4e992b0b13 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/model/serviceclientconfiguration.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/model/serviceclientconfiguration.java @@ -4,9 +4,18 @@ import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkPublicApi; import software.amazon.awssdk.awscore.AwsServiceClientConfiguration; +import software.amazon.awssdk.awscore.client.config.AwsClientOption; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +import software.amazon.awssdk.core.client.config.SdkClientConfiguration; +import software.amazon.awssdk.core.client.config.SdkClientOption; +import software.amazon.awssdk.core.internal.SdkInternalAdvancedClientOption; import software.amazon.awssdk.endpoints.EndpointProvider; +import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeProvider; +import software.amazon.awssdk.identity.spi.AwsCredentialsIdentity; +import software.amazon.awssdk.identity.spi.IdentityProvider; import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.jsonprotocoltests.auth.scheme.JsonProtocolTestsAuthSchemeProvider; +import software.amazon.awssdk.utils.Validate; /** * Class to expose the service client settings to the user. Implementation of {@link AwsServiceClientConfiguration} @@ -22,74 +31,218 @@ public static Builder builder() { return new BuilderImpl(); } + public static Builder builder(SdkClientConfiguration.Builder builder) { + return new BuilderImpl(builder); + } + /** * A builder for creating a {@link JsonProtocolTestsServiceClientConfiguration} */ public interface Builder extends AwsServiceClientConfiguration.Builder { + /** + * Sets the value for client override configuration + */ @Override - JsonProtocolTestsServiceClientConfiguration build(); + Builder overrideConfiguration(ClientOverrideConfiguration overrideConfiguration); + + /** + * Gets the value for client override configuration + */ + @Override + ClientOverrideConfiguration overrideConfiguration(); /** - * Configure the region + * Sets the value for AWS region */ @Override Builder region(Region region); /** - * Configure the endpointOverride + * Gets the value for AWS region + */ + @Override + Region region(); + + /** + * Sets the value for endpoint override */ @Override Builder endpointOverride(URI endpointOverride); /** - * Configure the client override configuration + * Gets the value for endpoint override */ @Override - Builder overrideConfiguration(ClientOverrideConfiguration clientOverrideConfiguration); + URI endpointOverride(); /** - * Configure the endpointProvider + * Sets the value for endpoint provider */ @Override Builder endpointProvider(EndpointProvider endpointProvider); + /** + * Gets the value for endpoint provider + */ + @Override + EndpointProvider endpointProvider(); + + /** + * Sets the value for credentials provider + */ + @Override + Builder credentialsProvider(IdentityProvider credentialsProvider); + + /** + * Gets the value for credentials provider + */ + @Override + IdentityProvider credentialsProvider(); + + /** + * Sets the value for auth scheme provider + */ + Builder authSchemeProvider(JsonProtocolTestsAuthSchemeProvider authSchemeProvider); + + /** + * Gets the value for auth scheme provider + */ + JsonProtocolTestsAuthSchemeProvider authSchemeProvider(); + + @Override + JsonProtocolTestsServiceClientConfiguration build(); } - private static final class BuilderImpl extends AwsServiceClientConfiguration.BuilderImpl implements Builder { + private static final class BuilderImpl implements Builder { + private final SdkClientConfiguration.Builder builder; + + private ClientOverrideConfiguration overrideConfiguration; + private BuilderImpl() { + this.builder = SdkClientConfiguration.builder(); } - private BuilderImpl(JsonProtocolTestsServiceClientConfiguration serviceClientConfiguration) { - super(serviceClientConfiguration); + private BuilderImpl(SdkClientConfiguration.Builder builder) { + this.builder = builder; } + /** + * Sets the value for client override configuration + */ @Override - public Builder region(Region region) { - this.region = region; + public Builder overrideConfiguration(ClientOverrideConfiguration overrideConfiguration) { + this.overrideConfiguration = overrideConfiguration; return this; } + /** + * Gets the value for client override configuration + */ + @Override + public ClientOverrideConfiguration overrideConfiguration() { + return overrideConfiguration; + } + + /** + * Sets the value for AWS region + */ @Override - public Builder overrideConfiguration(ClientOverrideConfiguration clientOverrideConfiguration) { - this.overrideConfiguration = clientOverrideConfiguration; + public Builder region(Region region) { + builder.option(AwsClientOption.AWS_REGION, region); return this; } + /** + * Gets the value for AWS region + */ + @Override + public Region region() { + return builder.option(AwsClientOption.AWS_REGION); + } + + /** + * Sets the value for endpoint override + */ @Override public Builder endpointOverride(URI endpointOverride) { - this.endpointOverride = endpointOverride; + builder.option(SdkInternalAdvancedClientOption.ENDPOINT_OVERRIDE_VALUE, endpointOverride); return this; } + /** + * Gets the value for endpoint override + */ + @Override + public URI endpointOverride() { + return builder.option(SdkInternalAdvancedClientOption.ENDPOINT_OVERRIDE_VALUE); + } + + /** + * Sets the value for endpoint provider + */ @Override public Builder endpointProvider(EndpointProvider endpointProvider) { - this.endpointProvider = endpointProvider; + builder.option(SdkClientOption.ENDPOINT_PROVIDER, endpointProvider); + return this; + } + + /** + * Gets the value for endpoint provider + */ + @Override + public EndpointProvider endpointProvider() { + return builder.option(SdkClientOption.ENDPOINT_PROVIDER); + } + + /** + * Sets the value for credentials provider + */ + @Override + public Builder credentialsProvider(IdentityProvider credentialsProvider) { + builder.option(AwsClientOption.CREDENTIALS_IDENTITY_PROVIDER, credentialsProvider); + return this; + } + + /** + * Gets the value for credentials provider + */ + @Override + public IdentityProvider credentialsProvider() { + return builder.option(AwsClientOption.CREDENTIALS_IDENTITY_PROVIDER); + } + + /** + * Sets the value for auth scheme provider + */ + @Override + public Builder authSchemeProvider(JsonProtocolTestsAuthSchemeProvider authSchemeProvider) { + builder.option(SdkClientOption.AUTH_SCHEME_PROVIDER, authSchemeProvider); return this; } + /** + * Gets the value for auth scheme provider + */ + @Override + public JsonProtocolTestsAuthSchemeProvider authSchemeProvider() { + AuthSchemeProvider result = builder.option(SdkClientOption.AUTH_SCHEME_PROVIDER); + if (result == null) { + return null; + } + return Validate.isInstanceOf(JsonProtocolTestsAuthSchemeProvider.class, result, "Expected an instance of " + + JsonProtocolTestsAuthSchemeProvider.class.getSimpleName()); + } + @Override public JsonProtocolTestsServiceClientConfiguration build() { return new JsonProtocolTestsServiceClientConfiguration(this); } + + public SdkClientConfiguration buildSdkClientConfiguration() { + if (overrideConfiguration != null) { + overrideConfiguration.addOverridesToConfiguration(builder); + } + return builder.build(); + } } } diff --git a/core/aws-core/src/main/java/software/amazon/awssdk/awscore/AwsServiceClientConfiguration.java b/core/aws-core/src/main/java/software/amazon/awssdk/awscore/AwsServiceClientConfiguration.java index 50aadac858ba..0f6146ce91ea 100644 --- a/core/aws-core/src/main/java/software/amazon/awssdk/awscore/AwsServiceClientConfiguration.java +++ b/core/aws-core/src/main/java/software/amazon/awssdk/awscore/AwsServiceClientConfiguration.java @@ -21,6 +21,8 @@ import software.amazon.awssdk.core.SdkServiceClientConfiguration; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.endpoints.EndpointProvider; +import software.amazon.awssdk.identity.spi.AwsCredentialsIdentity; +import software.amazon.awssdk.identity.spi.IdentityProvider; import software.amazon.awssdk.regions.Region; /** @@ -30,10 +32,12 @@ public abstract class AwsServiceClientConfiguration extends SdkServiceClientConfiguration { private final Region region; + private final IdentityProvider credentialsProvider; protected AwsServiceClientConfiguration(Builder builder) { super(builder); this.region = builder.region(); + this.credentialsProvider = builder.credentialsProvider(); } /** @@ -44,14 +48,11 @@ public Region region() { return this.region; } - @Override - public boolean equals(Object o) { - if (!super.equals(o)) { - return false; - } - - AwsServiceClientConfiguration serviceClientConfiguration = (AwsServiceClientConfiguration) o; - return Objects.equals(region, serviceClientConfiguration.region); + /** + * @return The configured identity provider + */ + public IdentityProvider credentialsProvider() { + return credentialsProvider; } @Override @@ -59,9 +60,21 @@ public int hashCode() { int result = 1; result = 31 * result + super.hashCode(); result = 31 * result + (region != null ? region.hashCode() : 0); + result = 31 * result + (credentialsProvider != null ? credentialsProvider.hashCode() : 0); return result; } + @Override + public boolean equals(Object o) { + if (!super.equals(o)) { + return false; + } + + AwsServiceClientConfiguration that = (AwsServiceClientConfiguration) o; + return Objects.equals(region, that.region) + && Objects.equals(credentialsProvider, that.credentialsProvider); + } + /** * The base interface for all AWS service client configuration builders */ @@ -95,6 +108,14 @@ default Builder endpointProvider(EndpointProvider endpointProvider) { throw new UnsupportedOperationException(); } + default Builder credentialsProvider(IdentityProvider credentialsProvider) { + throw new UnsupportedOperationException(); + } + + default IdentityProvider credentialsProvider() { + throw new UnsupportedOperationException(); + } + @Override AwsServiceClientConfiguration build(); } @@ -104,6 +125,7 @@ protected abstract static class BuilderImpl implements Builder { protected Region region; protected URI endpointOverride; protected EndpointProvider endpointProvider; + protected IdentityProvider credentialsProvider; protected BuilderImpl() { } @@ -135,6 +157,16 @@ public final EndpointProvider endpointProvider() { return endpointProvider; } + @Override + public final Builder credentialsProvider(IdentityProvider credentialsProvider) { + this.credentialsProvider = credentialsProvider; + return this; + } + + @Override + public final IdentityProvider credentialsProvider() { + return credentialsProvider; + } } } diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/builder/SdkDefaultClientBuilder.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/builder/SdkDefaultClientBuilder.java index 88a82d238d40..a4941dbbc5c2 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/builder/SdkDefaultClientBuilder.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/builder/SdkDefaultClientBuilder.java @@ -18,21 +18,14 @@ import static software.amazon.awssdk.core.ClientType.ASYNC; import static software.amazon.awssdk.core.ClientType.SYNC; import static software.amazon.awssdk.core.client.config.SdkAdvancedAsyncClientOption.FUTURE_COMPLETION_EXECUTOR; -import static software.amazon.awssdk.core.client.config.SdkAdvancedClientOption.DISABLE_HOST_PREFIX_INJECTION; -import static software.amazon.awssdk.core.client.config.SdkAdvancedClientOption.SIGNER; -import static software.amazon.awssdk.core.client.config.SdkAdvancedClientOption.TOKEN_SIGNER; import static software.amazon.awssdk.core.client.config.SdkAdvancedClientOption.USER_AGENT_PREFIX; import static software.amazon.awssdk.core.client.config.SdkAdvancedClientOption.USER_AGENT_SUFFIX; import static software.amazon.awssdk.core.client.config.SdkClientOption.ADDITIONAL_HTTP_HEADERS; -import static software.amazon.awssdk.core.client.config.SdkClientOption.API_CALL_ATTEMPT_TIMEOUT; -import static software.amazon.awssdk.core.client.config.SdkClientOption.API_CALL_TIMEOUT; import static software.amazon.awssdk.core.client.config.SdkClientOption.ASYNC_HTTP_CLIENT; import static software.amazon.awssdk.core.client.config.SdkClientOption.CLIENT_TYPE; import static software.amazon.awssdk.core.client.config.SdkClientOption.CLIENT_USER_AGENT; import static software.amazon.awssdk.core.client.config.SdkClientOption.COMPRESSION_CONFIGURATION; import static software.amazon.awssdk.core.client.config.SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED; -import static software.amazon.awssdk.core.client.config.SdkClientOption.ENDPOINT_OVERRIDDEN; -import static software.amazon.awssdk.core.client.config.SdkClientOption.EXECUTION_ATTRIBUTES; import static software.amazon.awssdk.core.client.config.SdkClientOption.EXECUTION_INTERCEPTORS; import static software.amazon.awssdk.core.client.config.SdkClientOption.IDENTITY_PROVIDERS; import static software.amazon.awssdk.core.client.config.SdkClientOption.INTERNAL_USER_AGENT; @@ -42,9 +35,7 @@ import static software.amazon.awssdk.core.client.config.SdkClientOption.PROFILE_NAME; import static software.amazon.awssdk.core.client.config.SdkClientOption.RETRY_POLICY; import static software.amazon.awssdk.core.client.config.SdkClientOption.SCHEDULED_EXECUTOR_SERVICE; -import static software.amazon.awssdk.core.client.config.SdkClientOption.SIGNER_OVERRIDDEN; import static software.amazon.awssdk.core.client.config.SdkClientOption.SYNC_HTTP_CLIENT; -import static software.amazon.awssdk.core.internal.SdkInternalTestAdvancedClientOption.ENDPOINT_OVERRIDDEN_OVERRIDE; import static software.amazon.awssdk.utils.CollectionUtils.mergeLists; import static software.amazon.awssdk.utils.Validate.paramNotNull; @@ -73,6 +64,7 @@ import software.amazon.awssdk.core.client.config.SdkClientOption; import software.amazon.awssdk.core.interceptor.ClasspathInterceptorChainFactory; import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; +import software.amazon.awssdk.core.internal.SdkInternalAdvancedClientOption; import software.amazon.awssdk.core.internal.http.loader.DefaultSdkAsyncHttpClientBuilder; import software.amazon.awssdk.core.internal.http.loader.DefaultSdkHttpClientBuilder; import software.amazon.awssdk.core.internal.http.pipeline.stages.ApplyUserAgentStage; @@ -223,38 +215,7 @@ private SdkClientConfiguration setOverrides(SdkClientConfiguration configuration if (clientOverrideConfiguration == null) { return configuration; } - - SdkClientConfiguration.Builder builder = configuration.toBuilder(); - - builder.option(SCHEDULED_EXECUTOR_SERVICE, clientOverrideConfiguration.scheduledExecutorService().orElse(null)); - builder.option(EXECUTION_INTERCEPTORS, clientOverrideConfiguration.executionInterceptors()); - builder.option(RETRY_POLICY, clientOverrideConfiguration.retryPolicy().orElse(null)); - builder.option(ADDITIONAL_HTTP_HEADERS, clientOverrideConfiguration.headers()); - builder.option(SIGNER, clientOverrideConfiguration.advancedOption(SIGNER).orElse(null)); - builder.option(USER_AGENT_SUFFIX, clientOverrideConfiguration.advancedOption(USER_AGENT_SUFFIX).orElse(null)); - builder.option(USER_AGENT_PREFIX, clientOverrideConfiguration.advancedOption(USER_AGENT_PREFIX).orElse(null)); - builder.option(API_CALL_TIMEOUT, clientOverrideConfiguration.apiCallTimeout().orElse(null)); - builder.option(API_CALL_ATTEMPT_TIMEOUT, clientOverrideConfiguration.apiCallAttemptTimeout().orElse(null)); - builder.option(DISABLE_HOST_PREFIX_INJECTION, - clientOverrideConfiguration.advancedOption(DISABLE_HOST_PREFIX_INJECTION).orElse(null)); - builder.option(PROFILE_FILE_SUPPLIER, clientOverrideConfiguration.defaultProfileFile() - .map(ProfileFileSupplier::fixedProfileFile) - .orElse(null)); - builder.option(PROFILE_NAME, clientOverrideConfiguration.defaultProfileName().orElse(null)); - builder.option(METRIC_PUBLISHERS, clientOverrideConfiguration.metricPublishers()); - builder.option(EXECUTION_ATTRIBUTES, clientOverrideConfiguration.executionAttributes()); - builder.option(TOKEN_SIGNER, clientOverrideConfiguration.advancedOption(TOKEN_SIGNER).orElse(null)); - builder.option(COMPRESSION_CONFIGURATION, clientOverrideConfiguration.compressionConfiguration().orElse(null)); - - clientOverrideConfiguration.advancedOption(ENDPOINT_OVERRIDDEN_OVERRIDE).ifPresent(value -> { - builder.option(ENDPOINT_OVERRIDDEN, value); - }); - - clientOverrideConfiguration.advancedOption(SIGNER).ifPresent(s -> { - builder.option(SIGNER_OVERRIDDEN, true); - }); - - return builder.build(); + return clientOverrideConfiguration.addOverridesToConfiguration(configuration.toBuilder()).build(); } /** @@ -524,10 +485,12 @@ private List sdkInterceptors() { public final B endpointOverride(URI endpointOverride) { if (endpointOverride == null) { clientConfiguration.option(SdkClientOption.ENDPOINT, null); + clientConfiguration.option(SdkInternalAdvancedClientOption.ENDPOINT_OVERRIDE_VALUE, null); clientConfiguration.option(SdkClientOption.ENDPOINT_OVERRIDDEN, false); } else { Validate.paramNotNull(endpointOverride.getScheme(), "The URI scheme of endpointOverride"); clientConfiguration.option(SdkClientOption.ENDPOINT, endpointOverride); + clientConfiguration.option(SdkInternalAdvancedClientOption.ENDPOINT_OVERRIDE_VALUE, endpointOverride); clientConfiguration.option(SdkClientOption.ENDPOINT_OVERRIDDEN, true); } return thisBuilder(); diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/config/ClientOverrideConfiguration.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/config/ClientOverrideConfiguration.java index dc3ce704a4d9..d088124b2929 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/config/ClientOverrideConfiguration.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/config/ClientOverrideConfiguration.java @@ -32,11 +32,14 @@ import software.amazon.awssdk.core.interceptor.ExecutionAttribute; import software.amazon.awssdk.core.interceptor.ExecutionAttributes; import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; +import software.amazon.awssdk.core.internal.SdkInternalTestAdvancedClientOption; import software.amazon.awssdk.core.retry.RetryMode; import software.amazon.awssdk.core.retry.RetryPolicy; +import software.amazon.awssdk.core.signer.Signer; import software.amazon.awssdk.core.sync.ResponseTransformer; import software.amazon.awssdk.metrics.MetricPublisher; import software.amazon.awssdk.profiles.ProfileFile; +import software.amazon.awssdk.profiles.ProfileFileSupplier; import software.amazon.awssdk.profiles.ProfileFileSystemSetting; import software.amazon.awssdk.utils.AttributeMap; import software.amazon.awssdk.utils.CollectionUtils; @@ -260,6 +263,49 @@ public String toString() { .build(); } + /** + * Adds the overridden values to the client configuration builder. + */ + public SdkClientConfiguration.Builder addOverridesToConfiguration(SdkClientConfiguration.Builder builder) { + // misc + builder.option(SdkClientOption.ADDITIONAL_HTTP_HEADERS, this.headers()); + builder.option(SdkClientOption.RETRY_POLICY, this.retryPolicy().orElse(null)); + builder.option(SdkClientOption.API_CALL_TIMEOUT, this.apiCallTimeout().orElse(null)); + builder.option(SdkClientOption.API_CALL_ATTEMPT_TIMEOUT, this.apiCallAttemptTimeout().orElse(null)); + builder.option(SdkClientOption.SCHEDULED_EXECUTOR_SERVICE, this.scheduledExecutorService().orElse(null)); + builder.option(SdkClientOption.EXECUTION_INTERCEPTORS, this.executionInterceptors()); + builder.option(SdkClientOption.EXECUTION_ATTRIBUTES, this.executionAttributes()); + + // advanced option + Signer signer = this.advancedOption(SdkAdvancedClientOption.SIGNER).orElse(null); + builder.option(SdkAdvancedClientOption.SIGNER, signer); + builder.option(SdkClientOption.SIGNER_OVERRIDDEN, signer != null); + builder.option(SdkAdvancedClientOption.USER_AGENT_SUFFIX, + this.advancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX).orElse(null)); + builder.option(SdkAdvancedClientOption.USER_AGENT_PREFIX, + this.advancedOption(SdkAdvancedClientOption.USER_AGENT_PREFIX).orElse(null)); + builder.option(SdkAdvancedClientOption.DISABLE_HOST_PREFIX_INJECTION, + this.advancedOption(SdkAdvancedClientOption.DISABLE_HOST_PREFIX_INJECTION).orElse(null)); + + // profile + builder.option(SdkClientOption.PROFILE_FILE_SUPPLIER, this.defaultProfileFile() + .map(ProfileFileSupplier::fixedProfileFile) + .orElse(null)); + builder.option(SdkClientOption.PROFILE_NAME, this.defaultProfileName().orElse(null)); + + // misc + builder.option(SdkClientOption.METRIC_PUBLISHERS, this.metricPublishers()); + builder.option(SdkAdvancedClientOption.TOKEN_SIGNER, + this.advancedOption(SdkAdvancedClientOption.TOKEN_SIGNER).orElse(null)); + builder.option(SdkClientOption.COMPRESSION_CONFIGURATION, this.compressionConfiguration().orElse(null)); + + this.advancedOption(SdkInternalTestAdvancedClientOption.ENDPOINT_OVERRIDDEN_OVERRIDE).ifPresent(value -> { + builder.option(SdkClientOption.ENDPOINT_OVERRIDDEN, value); + }); + + return builder; + } + /** * A builder for {@link ClientOverrideConfiguration}. * diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/config/SdkClientConfiguration.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/config/SdkClientConfiguration.java index aabc7a5ba631..8c389ea4f9d2 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/config/SdkClientConfiguration.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/config/SdkClientConfiguration.java @@ -113,6 +113,13 @@ public Builder option(ClientOption option, T value) { return this; } + /** + * Retrieve the value of a specific option. + */ + public T option(ClientOption option) { + return this.attributes.get(option); + } + @Override public SdkClientConfiguration build() { return new SdkClientConfiguration(attributes.build()); diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/SdkInternalAdvancedClientOption.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/SdkInternalAdvancedClientOption.java new file mode 100644 index 000000000000..41d9a1f09197 --- /dev/null +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/SdkInternalAdvancedClientOption.java @@ -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 software.amazon.awssdk.core.internal; + +import java.net.URI; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.core.SdkServiceClientConfiguration; +import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption; +import software.amazon.awssdk.core.client.config.SdkClientOption; + +/** + * Options of {@link SdkAdvancedClientOption} that must not be used outside of internals of this project. Changes to this + * class are not guaranteed to be backwards compatible. + */ +@SdkInternalApi +public class SdkInternalAdvancedClientOption extends SdkAdvancedClientOption { + /** + * The endpoint override is not currently reflected in the client options. We set its value using this internal option to + * allow to reconstruct the {@link SdkServiceClientConfiguration} with the same set of values without having to branch on + * whether the {@link SdkClientOption#ENDPOINT_OVERRIDDEN} was set. + */ + @SdkInternalApi + public static final SdkInternalAdvancedClientOption ENDPOINT_OVERRIDE_VALUE = + new SdkInternalAdvancedClientOption<>(URI.class); + + protected SdkInternalAdvancedClientOption(Class valueClass) { + super(valueClass); + } +}