> concreteAuthSchemeClasses = authSchemeSpecUtils.allServiceConcreteAuthSchemeClasses();
+ builder.addStatement("$T schemes = new $T<>($L + this.additionalAuthSchemes.size())",
+ returns, HashMap.class, concreteAuthSchemeClasses.size());
+ for (Class> concreteAuthScheme : concreteAuthSchemeClasses) {
+ String instanceVariable = CodegenNamingUtils.lowercaseFirstChar(concreteAuthScheme.getSimpleName());
+ builder.addStatement("$1T $2L = $1T.create()", concreteAuthScheme, instanceVariable);
+ builder.addStatement("schemes.put($1N.schemeId(), $1N)", instanceVariable);
+ }
+ builder.addStatement("schemes.putAll(this.additionalAuthSchemes)");
+ builder.addStatement("return $T.unmodifiableMap(schemes)", Collections.class);
+ return builder.build();
+ }
+
+ private MethodSpec invokePluginsMethod() {
+ MethodSpec.Builder builder = MethodSpec.methodBuilder("invokePlugins")
+ .addAnnotation(Override.class)
+ .addModifiers(PROTECTED)
+ .addParameter(SdkClientConfiguration.class, "config")
+ .returns(SdkClientConfiguration.class);
+ builder.addStatement("$T plugins = plugins()",
+ ParameterizedTypeName.get(List.class, SdkPlugin.class))
+ .beginControlFlow("if (plugins.isEmpty())")
+ .addStatement("return config")
+ .endControlFlow();
+ builder.addStatement("$1T.BuilderInternal serviceConfigBuilder = $1T.builder(config.toBuilder())",
+ configurationUtils.serviceClientConfigurationBuilderClassName());
+ builder.addStatement("serviceConfigBuilder.overrideConfiguration(overrideConfiguration())");
+ builder.beginControlFlow("for ($T plugin : plugins)", SdkPlugin.class)
+ .addStatement("plugin.configureClient(serviceConfigBuilder)")
+ .endControlFlow();
+ builder.addStatement("overrideConfiguration(serviceConfigBuilder.overrideConfiguration())");
+ builder.addStatement("return serviceConfigBuilder.buildSdkClientConfiguration()");
+ return builder.build();
+ }
+
+ private MethodSpec setOverridesMethod() {
+ return MethodSpec.methodBuilder("setOverrides")
+ .addModifiers(PROTECTED)
+ .addAnnotation(Override.class)
+ .addParameter(SdkClientConfiguration.class, "configuration")
+ .returns(SdkClientConfiguration.class)
+ .addStatement("$T overrideConfiguration = overrideConfiguration()",
+ ClientOverrideConfiguration.class)
+ .beginControlFlow("if (overrideConfiguration == null)")
+ .addStatement("return configuration")
+ .endControlFlow()
+ .addStatement("return $T.copyOverridesToConfiguration(overrideConfiguration, configuration.toBuilder())"
+ + ".build()",
+ sdkClientConfigurationUtilClassName)
+ .build();
+ }
+
@Override
public ClassName className() {
return builderClassName;
@@ -637,7 +792,7 @@ private MethodSpec validateClientOptionsMethod() {
.addParameter(SdkClientConfiguration.class, "c")
.returns(void.class);
- if (AuthUtils.usesAwsAuth(model)) {
+ if (AuthUtils.usesAwsAuth(model) && !authSchemeSpecUtils.useSraAuth()) {
builder.addStatement("$T.notNull(c.option($T.SIGNER), $S)",
Validate.class,
SdkAdvancedClientOption.class,
@@ -645,16 +800,17 @@ private MethodSpec validateClientOptionsMethod() {
}
if (AuthUtils.usesBearerAuth(model)) {
- builder.addStatement("$T.notNull(c.option($T.TOKEN_SIGNER), $S)",
- Validate.class,
- SdkAdvancedClientOption.class,
- "The 'overrideConfiguration.advancedOption[TOKEN_SIGNER]' "
- + "must be configured in the client builder.");
- builder.addStatement("$T.notNull(c.option($T.TOKEN_PROVIDER), $S)",
+ if (!authSchemeSpecUtils.useSraAuth()) {
+ builder.addStatement("$T.notNull(c.option($T.TOKEN_SIGNER), $S)",
+ Validate.class,
+ SdkAdvancedClientOption.class,
+ "The 'overrideConfiguration.advancedOption[TOKEN_SIGNER]' "
+ + "must be configured in the client builder.");
+ }
+ builder.addStatement("$T.notNull(c.option($T.TOKEN_IDENTITY_PROVIDER), $S)",
Validate.class,
AwsClientOption.class,
- "The 'overrideConfiguration.advancedOption[TOKEN_PROVIDER]' "
- + "must be configured in the client builder.");
+ "The 'tokenProvider' must be configured in the client builder.");
}
return builder.build();
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/builder/BaseClientBuilderInterface.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/builder/BaseClientBuilderInterface.java
index 0aac740152bc..44700c69f8a3 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/builder/BaseClientBuilderInterface.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/builder/BaseClientBuilderInterface.java
@@ -22,6 +22,7 @@
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
import com.squareup.javapoet.TypeVariableName;
+import com.squareup.javapoet.WildcardTypeName;
import java.util.function.Consumer;
import javax.lang.model.element.Modifier;
import software.amazon.awssdk.auth.token.credentials.SdkTokenProvider;
@@ -33,22 +34,30 @@
import software.amazon.awssdk.codegen.model.service.ClientContextParam;
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.codegen.poet.rules.EndpointRulesSpecUtils;
import software.amazon.awssdk.codegen.utils.AuthUtils;
import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption;
+import software.amazon.awssdk.identity.spi.IdentityProvider;
+import software.amazon.awssdk.identity.spi.TokenIdentity;
import software.amazon.awssdk.utils.internal.CodegenNamingUtils;
public class BaseClientBuilderInterface implements ClassSpec {
+ private static final ParameterizedTypeName TOKEN_IDENTITY_PROVIDER_TYPE_NAME =
+ ParameterizedTypeName.get(ClassName.get(IdentityProvider.class), WildcardTypeName.subtypeOf(TokenIdentity.class));
+
private final IntermediateModel model;
private final String basePackage;
private final ClassName builderInterfaceName;
private final EndpointRulesSpecUtils endpointRulesSpecUtils;
+ private final AuthSchemeSpecUtils authSchemeSpecUtils;
public BaseClientBuilderInterface(IntermediateModel model) {
this.model = model;
this.basePackage = model.getMetadata().getFullClientPackageName();
this.builderInterfaceName = ClassName.get(basePackage, model.getMetadata().getBaseBuilderInterface());
this.endpointRulesSpecUtils = new EndpointRulesSpecUtils(model);
+ this.authSchemeSpecUtils = new AuthSchemeSpecUtils(model);
}
@Override
@@ -73,6 +82,7 @@ public TypeSpec poetSpec() {
}
builder.addMethod(endpointProviderMethod());
+ builder.addMethod(authSchemeProviderMethod());
if (hasClientContextParams()) {
model.getClientContextParams().forEach((n, m) -> {
@@ -88,6 +98,7 @@ public TypeSpec poetSpec() {
if (generateTokenProviderMethod()) {
builder.addMethod(tokenProviderMethod());
+ builder.addMethod(tokenIdentityProviderMethod());
}
return builder.build();
@@ -154,6 +165,19 @@ private MethodSpec endpointProviderMethod() {
.build();
}
+ private MethodSpec authSchemeProviderMethod() {
+ return MethodSpec.methodBuilder("authSchemeProvider")
+ .addModifiers(Modifier.PUBLIC, Modifier.DEFAULT)
+ .addParameter(authSchemeSpecUtils.providerInterfaceName(), "authSchemeProvider")
+ .addJavadoc("Set the {@link $T} implementation that will be used by the client to resolve the "
+ + "auth scheme for each request. This is optional; if none is provided a "
+ + "default implementation will be used the SDK.",
+ authSchemeSpecUtils.providerInterfaceName())
+ .returns(TypeVariableName.get("B"))
+ .addStatement("throw new $T()", UnsupportedOperationException.class)
+ .build();
+ }
+
private MethodSpec clientContextParamSetter(String name, ClientContextParam param) {
String setterName = Utils.unCapitalize(CodegenNamingUtils.pascalCase(name));
TypeName type = endpointRulesSpecUtils.toJavaType(param.getType());
@@ -174,7 +198,7 @@ private boolean generateTokenProviderMethod() {
private MethodSpec tokenProviderMethod() {
return MethodSpec.methodBuilder("tokenProvider")
- .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
+ .addModifiers(Modifier.PUBLIC, Modifier.DEFAULT)
.returns(TypeVariableName.get("B"))
.addParameter(SdkTokenProvider.class, "tokenProvider")
.addJavadoc("Set the token provider to use for bearer token authorization. This is optional, if none "
@@ -188,6 +212,27 @@ private MethodSpec tokenProviderMethod() {
DefaultAwsTokenProvider.class,
SdkAdvancedClientOption.class,
BearerTokenSigner.class)
+ .addStatement("return tokenProvider(($T) tokenProvider)", TOKEN_IDENTITY_PROVIDER_TYPE_NAME)
+ .build();
+ }
+
+ private MethodSpec tokenIdentityProviderMethod() {
+ return MethodSpec.methodBuilder("tokenProvider")
+ .addModifiers(Modifier.PUBLIC, Modifier.DEFAULT)
+ .returns(TypeVariableName.get("B"))
+ .addParameter(TOKEN_IDENTITY_PROVIDER_TYPE_NAME, "tokenProvider")
+ .addJavadoc("Set the token provider to use for bearer token authorization. This is optional, if none "
+ + "is provided, the SDK will use {@link $T}.\n"
+ + "\n"
+ + "If the service, or any of its operations require Bearer Token Authorization, then the "
+ + "SDK will default to this token provider to retrieve the token to use for authorization.\n"
+ + "
\n"
+ + "This provider works in conjunction with the {@code $T.TOKEN_SIGNER} set on the client. "
+ + "By default it is {@link $T}.",
+ DefaultAwsTokenProvider.class,
+ SdkAdvancedClientOption.class,
+ BearerTokenSigner.class)
+ .addStatement("throw new $T()", UnsupportedOperationException.class)
.build();
}
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 bb5fd4f2208c..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
@@ -19,10 +19,10 @@
import com.squareup.javapoet.MethodSpec;
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.auth.token.credentials.SdkTokenProvider;
import software.amazon.awssdk.awscore.client.config.AwsClientOption;
import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
import software.amazon.awssdk.codegen.poet.ClassSpec;
@@ -32,7 +32,8 @@
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;
public class SyncClientBuilderClass implements ClassSpec {
private final IntermediateModel model;
@@ -59,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());
@@ -81,7 +82,7 @@ public TypeSpec poetSpec() {
}
builder.addMethod(buildClientMethod());
- builder.addMethod(initializeServiceClientConfigMethod());
+ builder.addMethod(initializeServiceClientConfigMethod(serviceConfigClassName));
return builder.build();
}
@@ -124,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);
@@ -146,36 +147,35 @@ private MethodSpec buildClientMethod() {
}
private MethodSpec tokenProviderMethodImpl() {
+ ParameterizedTypeName tokenProviderTypeName = ParameterizedTypeName.get(ClassName.get(IdentityProvider.class),
+ WildcardTypeName.subtypeOf(TokenIdentity.class));
return MethodSpec.methodBuilder("tokenProvider").addModifiers(Modifier.PUBLIC)
.addAnnotation(Override.class)
- .addParameter(SdkTokenProvider.class, "tokenProvider")
+ .addParameter(tokenProviderTypeName, "tokenProvider")
.returns(builderClassName)
- .addStatement("clientConfiguration.option($T.TOKEN_PROVIDER, tokenProvider)",
+ .addStatement("clientConfiguration.option($T.TOKEN_IDENTITY_PROVIDER, tokenProvider)",
AwsClientOption.class)
.addStatement("return this")
.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/client/AsyncClientClass.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/AsyncClientClass.java
index 9b66f9a28259..9c3a8b8127d2 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/AsyncClientClass.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/AsyncClientClass.java
@@ -34,6 +34,7 @@
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.nio.ByteBuffer;
import java.util.ArrayList;
@@ -65,10 +66,14 @@
import software.amazon.awssdk.codegen.poet.PoetExtension;
import software.amazon.awssdk.codegen.poet.PoetUtils;
import software.amazon.awssdk.codegen.poet.StaticImport;
+import software.amazon.awssdk.codegen.poet.auth.scheme.AuthSchemeSpecUtils;
import software.amazon.awssdk.codegen.poet.client.specs.ProtocolSpec;
import software.amazon.awssdk.codegen.poet.eventstream.EventStreamUtils;
import software.amazon.awssdk.codegen.poet.model.EventStreamSpecHelper;
+import software.amazon.awssdk.codegen.poet.model.ServiceClientConfigurationUtils;
import software.amazon.awssdk.core.RequestOverrideConfiguration;
+import software.amazon.awssdk.core.SdkPlugin;
+import software.amazon.awssdk.core.SdkRequest;
import software.amazon.awssdk.core.async.AsyncResponseTransformer;
import software.amazon.awssdk.core.async.AsyncResponseTransformerUtils;
import software.amazon.awssdk.core.async.SdkPublisher;
@@ -79,6 +84,7 @@
import software.amazon.awssdk.core.endpointdiscovery.EndpointDiscoveryRefreshCache;
import software.amazon.awssdk.core.endpointdiscovery.EndpointDiscoveryRequest;
import software.amazon.awssdk.core.metrics.CoreMetric;
+import software.amazon.awssdk.identity.spi.AwsCredentialsIdentity;
import software.amazon.awssdk.metrics.MetricCollector;
import software.amazon.awssdk.metrics.MetricPublisher;
import software.amazon.awssdk.metrics.NoOpMetricCollector;
@@ -93,6 +99,8 @@ public final class AsyncClientClass extends AsyncClientInterface {
private final ClassName className;
private final ProtocolSpec protocolSpec;
private final ClassName serviceClientConfigurationClassName;
+ private final ServiceClientConfigurationUtils configurationUtils;
+ private final boolean useSraAuth;
public AsyncClientClass(GeneratorTaskParams dependencies) {
super(dependencies.getModel());
@@ -101,6 +109,8 @@ public AsyncClientClass(GeneratorTaskParams dependencies) {
this.className = poetExtensions.getClientClass(model.getMetadata().getAsyncClient());
this.protocolSpec = getProtocolSpecs(poetExtensions, model);
this.serviceClientConfigurationClassName = new PoetExtension(model).getServiceConfigClass();
+ this.useSraAuth = new AuthSchemeSpecUtils(model).useSraAuth();
+ this.configurationUtils = new ServiceClientConfigurationUtils(model);
}
@Override
@@ -154,11 +164,13 @@ protected void addAdditionalMethods(TypeSpec.Builder type) {
.addMethod(protocolSpec.initProtocolFactory(model))
.addMethod(resolveMetricPublishersMethod());
- if (model.containsRequestSigners() || model.containsRequestEventStreams() || hasStreamingV4AuthOperations()) {
- type.addMethod(applySignerOverrideMethod(poetExtensions, model));
- type.addMethod(isSignerOverriddenOnClientMethod());
+ if (!useSraAuth) {
+ if (model.containsRequestSigners() || model.containsRequestEventStreams() || hasStreamingV4AuthOperations()) {
+ type.addMethod(applySignerOverrideMethod(poetExtensions, model));
+ type.addMethod(isSignerOverriddenOnClientMethod());
+ }
}
-
+ type.addMethod(updateSdkClientConfigurationMethod(configurationUtils.serviceClientConfigurationBuilderClassName()));
protocolSpec.createErrorResponseHandler().ifPresent(type::addMethod);
}
@@ -271,6 +283,31 @@ protected MethodSpec serviceClientConfigMethod() {
.build();
}
+ protected static MethodSpec updateSdkClientConfigurationMethod(
+ TypeName serviceClientConfigurationBuilderClassName) {
+ MethodSpec.Builder builder = MethodSpec.methodBuilder("updateSdkClientConfiguration")
+ .addModifiers(PRIVATE)
+ .addParameter(SdkRequest.class, "request")
+ .addParameter(SdkClientConfiguration.class, "clientConfiguration")
+ .returns(SdkClientConfiguration.class);
+
+
+ builder.addStatement("$T plugins = request.overrideConfiguration()\n"
+ + ".map(c -> c.plugins()).orElse(Collections.emptyList())",
+ ParameterizedTypeName.get(List.class, SdkPlugin.class))
+ .beginControlFlow("if (plugins.isEmpty())")
+ .addStatement("return clientConfiguration")
+ .endControlFlow();
+ builder.addStatement("$1T.BuilderInternal serviceConfigBuilder = $1T.builder(clientConfiguration.toBuilder())",
+ serviceClientConfigurationBuilderClassName);
+ builder.addStatement("serviceConfigBuilder.overrideConfiguration(serviceClientConfiguration.overrideConfiguration())");
+ builder.beginControlFlow("for ($T plugin : plugins)", SdkPlugin.class)
+ .addStatement("plugin.configureClient(serviceConfigBuilder)")
+ .endControlFlow();
+ builder.addStatement("return serviceConfigBuilder.buildSdkClientConfiguration()");
+ return builder.build();
+ }
+
@Override
protected void addCloseMethod(TypeSpec.Builder type) {
MethodSpec method = MethodSpec.methodBuilder("close")
@@ -287,7 +324,8 @@ protected MethodSpec.Builder operationBody(MethodSpec.Builder builder, Operation
builder.addModifiers(PUBLIC)
.addAnnotation(Override.class);
-
+ builder.addStatement("$T clientConfiguration = updateSdkClientConfiguration($L, this.clientConfiguration)",
+ SdkClientConfiguration.class, opModel.getInput().getVariableName());
builder.addStatement("$T<$T> metricPublishers = "
+ "resolveMetricPublishers(clientConfiguration, $N.overrideConfiguration().orElse(null))",
List.class,
@@ -325,11 +363,13 @@ protected MethodSpec.Builder operationBody(MethodSpec.Builder builder, Operation
"endOfStreamFuture",
"pair");
}
-
- if (shouldUseAsyncWithBodySigner(opModel)) {
- builder.addCode(applyAsyncWithBodyV4SignerOverride(opModel));
- } else {
- builder.addCode(ClientClassUtils.callApplySignerOverrideMethod(opModel));
+
+ if (!useSraAuth) {
+ if (shouldUseAsyncWithBodySigner(opModel)) {
+ builder.addCode(applyAsyncWithBodyV4SignerOverride(opModel));
+ } else {
+ builder.addCode(ClientClassUtils.callApplySignerOverrideMethod(opModel));
+ }
}
builder.addCode(protocolSpec.responseHandler(model, opModel));
@@ -366,22 +406,29 @@ protected MethodSpec.Builder operationBody(MethodSpec.Builder builder, Operation
}
}
- builder.addStatement("$T cachedEndpoint = null", URI.class);
+ builder.addStatement("$T<$T> endpointFuture = $T.completedFuture(null)",
+ CompletableFuture.class, URI.class, CompletableFuture.class);
builder.beginControlFlow("if (endpointDiscoveryEnabled)");
- builder.addCode("$T key = $N.overrideConfiguration()", String.class, opModel.getInput().getVariableName())
- .addCode(" .flatMap($T::credentialsProvider)", AwsRequestOverrideConfiguration.class)
- .addCode(" .orElseGet(() -> clientConfiguration.option($T.CREDENTIALS_PROVIDER))", AwsClientOption.class)
- .addCode(" .resolveCredentials().accessKeyId();");
-
- builder.addCode("$1T endpointDiscoveryRequest = $1T.builder()", EndpointDiscoveryRequest.class)
- .addCode(" .required($L)", opModel.getInputShape().getEndpointDiscovery().isRequired())
- .addCode(" .defaultEndpoint(clientConfiguration.option($T.ENDPOINT))", SdkClientOption.class)
- .addCode(" .overrideConfiguration($N.overrideConfiguration().orElse(null))",
+ ParameterizedTypeName identityFutureTypeName = ParameterizedTypeName.get(ClassName.get(CompletableFuture.class),
+ WildcardTypeName.subtypeOf(AwsCredentialsIdentity.class));
+ builder.addCode("$T identityFuture = $N.overrideConfiguration()", identityFutureTypeName,
+ opModel.getInput().getVariableName())
+ .addCode(" .flatMap($T::credentialsIdentityProvider)", AwsRequestOverrideConfiguration.class)
+ .addCode(" .orElseGet(() -> clientConfiguration.option($T.CREDENTIALS_IDENTITY_PROVIDER))",
+ AwsClientOption.class)
+ .addCode(" .resolveIdentity();");
+
+ builder.addCode("endpointFuture = identityFuture.thenApply(credentials -> {")
+ .addCode(" $1T endpointDiscoveryRequest = $1T.builder()", EndpointDiscoveryRequest.class)
+ .addCode(" .required($L)", opModel.getInputShape().getEndpointDiscovery().isRequired())
+ .addCode(" .defaultEndpoint(clientConfiguration.option($T.ENDPOINT))", SdkClientOption.class)
+ .addCode(" .overrideConfiguration($N.overrideConfiguration().orElse(null))",
opModel.getInput().getVariableName())
- .addCode(" .build();");
+ .addCode(" .build();")
+ .addCode(" return endpointDiscoveryCache.get(credentials.accessKeyId(), endpointDiscoveryRequest);")
+ .addCode("});");
- builder.addStatement("cachedEndpoint = endpointDiscoveryCache.get(key, endpointDiscoveryRequest)");
builder.endControlFlow();
}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/SyncClientClass.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/SyncClientClass.java
index 310170284bfe..2ec170acfd15 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/SyncClientClass.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/SyncClientClass.java
@@ -20,6 +20,7 @@
import static javax.lang.model.element.Modifier.PROTECTED;
import static javax.lang.model.element.Modifier.PUBLIC;
import static javax.lang.model.element.Modifier.STATIC;
+import static software.amazon.awssdk.codegen.poet.client.AsyncClientClass.updateSdkClientConfigurationMethod;
import static software.amazon.awssdk.codegen.poet.client.ClientClassUtils.addS3ArnableFieldCode;
import static software.amazon.awssdk.codegen.poet.client.ClientClassUtils.applySignerOverrideMethod;
@@ -28,10 +29,12 @@
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeSpec;
+import com.squareup.javapoet.WildcardTypeName;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import software.amazon.awssdk.annotations.SdkInternalApi;
@@ -44,11 +47,13 @@
import software.amazon.awssdk.codegen.model.intermediate.Protocol;
import software.amazon.awssdk.codegen.poet.PoetExtension;
import software.amazon.awssdk.codegen.poet.PoetUtils;
+import software.amazon.awssdk.codegen.poet.auth.scheme.AuthSchemeSpecUtils;
import software.amazon.awssdk.codegen.poet.client.specs.Ec2ProtocolSpec;
import software.amazon.awssdk.codegen.poet.client.specs.JsonProtocolSpec;
import software.amazon.awssdk.codegen.poet.client.specs.ProtocolSpec;
import software.amazon.awssdk.codegen.poet.client.specs.QueryProtocolSpec;
import software.amazon.awssdk.codegen.poet.client.specs.XmlProtocolSpec;
+import software.amazon.awssdk.codegen.poet.model.ServiceClientConfigurationUtils;
import software.amazon.awssdk.core.RequestOverrideConfiguration;
import software.amazon.awssdk.core.client.config.SdkClientConfiguration;
import software.amazon.awssdk.core.client.config.SdkClientOption;
@@ -56,9 +61,11 @@
import software.amazon.awssdk.core.endpointdiscovery.EndpointDiscoveryRefreshCache;
import software.amazon.awssdk.core.endpointdiscovery.EndpointDiscoveryRequest;
import software.amazon.awssdk.core.metrics.CoreMetric;
+import software.amazon.awssdk.identity.spi.AwsCredentialsIdentity;
import software.amazon.awssdk.metrics.MetricCollector;
import software.amazon.awssdk.metrics.MetricPublisher;
import software.amazon.awssdk.metrics.NoOpMetricCollector;
+import software.amazon.awssdk.utils.CompletableFutureUtils;
import software.amazon.awssdk.utils.Logger;
public class SyncClientClass extends SyncClientInterface {
@@ -68,6 +75,8 @@ public class SyncClientClass extends SyncClientInterface {
private final ClassName className;
private final ProtocolSpec protocolSpec;
private final ClassName serviceClientConfigurationClassName;
+ private final ServiceClientConfigurationUtils configurationUtils;
+ private final boolean useSraAuth;
public SyncClientClass(GeneratorTaskParams taskParams) {
super(taskParams.getModel());
@@ -76,6 +85,8 @@ public SyncClientClass(GeneratorTaskParams taskParams) {
this.className = poetExtensions.getClientClass(model.getMetadata().getSyncClient());
this.protocolSpec = getProtocolSpecs(poetExtensions, model);
this.serviceClientConfigurationClassName = new PoetExtension(model).getServiceConfigClass();
+ this.configurationUtils = new ServiceClientConfigurationUtils(model);
+ this.useSraAuth = new AuthSchemeSpecUtils(model).useSraAuth();
}
@Override
@@ -111,9 +122,10 @@ protected void addFields(TypeSpec.Builder type) {
@Override
protected void addAdditionalMethods(TypeSpec.Builder type) {
-
- if (model.containsRequestSigners()) {
- type.addMethod(applySignerOverrideMethod(poetExtensions, model));
+ if (!useSraAuth) {
+ if (model.containsRequestSigners()) {
+ type.addMethod(applySignerOverrideMethod(poetExtensions, model));
+ }
}
model.getEndpointOperation().ifPresent(
@@ -125,7 +137,7 @@ protected void addAdditionalMethods(TypeSpec.Builder type) {
.addMethod(resolveMetricPublishersMethod());
protocolSpec.createErrorResponseHandler().ifPresent(type::addMethod);
-
+ type.addMethod(updateSdkClientConfigurationMethod(configurationUtils.serviceClientConfigurationBuilderClassName()));
type.addMethod(protocolSpec.initProtocolFactory(model));
}
@@ -168,6 +180,7 @@ private MethodSpec constructor() {
.addStatement("this.clientHandler = new $T(clientConfiguration)", protocolSpec.getClientHandlerClass())
.addStatement("this.clientConfiguration = clientConfiguration")
.addStatement("this.serviceClientConfiguration = serviceClientConfiguration");
+
FieldSpec protocolFactoryField = protocolSpec.protocolFactory(model);
if (model.getMetadata().isJsonProtocol()) {
builder.addStatement("this.$N = init($T.builder()).build()", protocolFactoryField.name,
@@ -216,9 +229,11 @@ private Stream operations(OperationModel opModel) {
private MethodSpec traditionalMethod(OperationModel opModel) {
MethodSpec.Builder method = SyncClientInterface.operationMethodSignature(model, opModel)
- .addAnnotation(Override.class)
- .addCode(ClientClassUtils.callApplySignerOverrideMethod(opModel))
- .addCode(protocolSpec.responseHandler(model, opModel));
+ .addAnnotation(Override.class);
+ if (!useSraAuth) {
+ method.addCode(ClientClassUtils.callApplySignerOverrideMethod(opModel));
+ }
+ method.addCode(protocolSpec.responseHandler(model, opModel));
protocolSpec.errorResponseHandler(opModel).ifPresent(method::addCode);
@@ -255,10 +270,18 @@ private MethodSpec traditionalMethod(OperationModel opModel) {
method.addStatement("$T cachedEndpoint = null", URI.class);
method.beginControlFlow("if (endpointDiscoveryEnabled)");
- method.addCode("$T key = $N.overrideConfiguration()", String.class, opModel.getInput().getVariableName())
- .addCode(" .flatMap($T::credentialsProvider)", AwsRequestOverrideConfiguration.class)
- .addCode(" .orElseGet(() -> clientConfiguration.option($T.CREDENTIALS_PROVIDER))", AwsClientOption.class)
- .addCode(" .resolveCredentials().accessKeyId();");
+ ParameterizedTypeName identityFutureTypeName =
+ ParameterizedTypeName.get(ClassName.get(CompletableFuture.class),
+ WildcardTypeName.subtypeOf(AwsCredentialsIdentity.class));
+ method.addCode("$T identityFuture = $N.overrideConfiguration()",
+ identityFutureTypeName,
+ opModel.getInput().getVariableName())
+ .addCode(" .flatMap($T::credentialsIdentityProvider)", AwsRequestOverrideConfiguration.class)
+ .addCode(" .orElseGet(() -> clientConfiguration.option($T.CREDENTIALS_IDENTITY_PROVIDER))",
+ AwsClientOption.class)
+ .addCode(" .resolveIdentity();");
+
+ method.addCode("$T key = $T.joinLikeSync(identityFuture).accessKeyId();", String.class, CompletableFutureUtils.class);
method.addCode("$1T endpointDiscoveryRequest = $1T.builder()", EndpointDiscoveryRequest.class)
.addCode(" .required($L)", opModel.getInputShape().getEndpointDiscovery().isRequired())
@@ -271,6 +294,8 @@ private MethodSpec traditionalMethod(OperationModel opModel) {
method.endControlFlow();
}
+ method.addStatement("$T clientConfiguration = updateSdkClientConfiguration($L, this.clientConfiguration)",
+ SdkClientConfiguration.class, opModel.getInput().getVariableName());
method.addStatement("$T<$T> metricPublishers = "
+ "resolveMetricPublishers(clientConfiguration, $N.overrideConfiguration().orElse(null))",
List.class,
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/SyncClientInterface.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/SyncClientInterface.java
index 5037d5eda1f2..a9f9f06d6049 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/SyncClientInterface.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/SyncClientInterface.java
@@ -142,6 +142,7 @@ protected void addAdditionalMethods(TypeSpec.Builder type) {
.addMethod(serviceMetadata());
PoetUtils.addJavadoc(type::addJavadoc, getJavadoc());
+
}
@Override
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/JsonProtocolSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/JsonProtocolSpec.java
index ce46ecf7c824..5d86cfd13078 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/JsonProtocolSpec.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/JsonProtocolSpec.java
@@ -39,6 +39,7 @@
import software.amazon.awssdk.codegen.model.intermediate.Protocol;
import software.amazon.awssdk.codegen.model.intermediate.ShapeModel;
import software.amazon.awssdk.codegen.poet.PoetExtension;
+import software.amazon.awssdk.codegen.poet.auth.scheme.AuthSchemeSpecUtils;
import software.amazon.awssdk.codegen.poet.client.traits.HttpChecksumRequiredTrait;
import software.amazon.awssdk.codegen.poet.client.traits.HttpChecksumTrait;
import software.amazon.awssdk.codegen.poet.client.traits.NoneAuthTypeRequestTrait;
@@ -64,10 +65,12 @@ public class JsonProtocolSpec implements ProtocolSpec {
private final PoetExtension poetExtensions;
private final IntermediateModel model;
+ private final boolean useSraAuth;
public JsonProtocolSpec(PoetExtension poetExtensions, IntermediateModel model) {
this.poetExtensions = poetExtensions;
this.model = model;
+ this.useSraAuth = new AuthSchemeSpecUtils(model).useSraAuth();
}
@Override
@@ -184,12 +187,17 @@ public CodeBlock executionHandler(OperationModel opModel) {
.add(hostPrefixExpression(opModel))
.add(discoveredEndpoint(opModel))
.add(credentialType(opModel, model))
+ .add(".withRequestConfiguration(clientConfiguration)")
.add(".withInput($L)\n", opModel.getInput().getVariableName())
.add(".withMetricCollector(apiCallMetricCollector)")
.add(HttpChecksumRequiredTrait.putHttpChecksumAttribute(opModel))
- .add(HttpChecksumTrait.create(opModel))
- .add(NoneAuthTypeRequestTrait.create(opModel))
- .add(RequestCompressionTrait.create(opModel, model));
+ .add(HttpChecksumTrait.create(opModel));
+
+ if (!useSraAuth) {
+ codeBlock.add(NoneAuthTypeRequestTrait.create(opModel));
+ }
+
+ codeBlock.add(RequestCompressionTrait.create(opModel, model));
if (opModel.hasStreamingInput()) {
codeBlock.add(".withRequestBody(requestBody)")
@@ -242,8 +250,9 @@ public CodeBlock asyncExecutionHandler(IntermediateModel intermediateModel, Oper
: pojoResponseType;
TypeName executeFutureValueType = executeFutureValueType(opModel, poetExtensions);
- builder.add("\n\n$T<$T> executeFuture = clientHandler.execute(new $T<$T, $T>()\n",
- CompletableFuture.class, executeFutureValueType, ClientExecutionParams.class, requestType, responseType)
+ builder.add("\n\n$T<$T> executeFuture = ", CompletableFuture.class, executeFutureValueType)
+ .add(opModel.getEndpointDiscovery() != null ? "endpointFuture.thenCompose(cachedEndpoint -> " : "")
+ .add("clientHandler.execute(new $T<$T, $T>()\n", ClientExecutionParams.class, requestType, responseType)
.add(".withOperationName(\"$N\")\n", opModel.getOperationName())
.add(".withMarshaller($L)\n", asyncMarshaller(model, opModel, marshaller, protocolFactory))
.add(asyncRequestBody(opModel))
@@ -251,17 +260,23 @@ public CodeBlock asyncExecutionHandler(IntermediateModel intermediateModel, Oper
.add(hasInitialRequestEvent(opModel, isRestJson))
.add(".withResponseHandler($L)\n", responseHandlerName(opModel, isRestJson))
.add(".withErrorResponseHandler(errorResponseHandler)\n")
+ .add(".withRequestConfiguration(clientConfiguration)")
.add(".withMetricCollector(apiCallMetricCollector)\n")
.add(hostPrefixExpression(opModel))
.add(discoveredEndpoint(opModel))
.add(credentialType(opModel, model))
.add(asyncRequestBody)
.add(HttpChecksumRequiredTrait.putHttpChecksumAttribute(opModel))
- .add(HttpChecksumTrait.create(opModel))
- .add(NoneAuthTypeRequestTrait.create(opModel))
- .add(RequestCompressionTrait.create(opModel, model))
- .add(".withInput($L)$L);",
- opModel.getInput().getVariableName(), asyncResponseTransformerVariable(isStreaming, isRestJson, opModel));
+ .add(HttpChecksumTrait.create(opModel));
+
+ if (!useSraAuth) {
+ builder.add(NoneAuthTypeRequestTrait.create(opModel));
+ }
+
+ builder.add(RequestCompressionTrait.create(opModel, model))
+ .add(".withInput($L)$L)",
+ opModel.getInput().getVariableName(), asyncResponseTransformerVariable(isStreaming, isRestJson, opModel))
+ .add(opModel.getEndpointDiscovery() != null ? ");" : ";");
if (opModel.hasStreamingOutput()) {
builder.addStatement("$T<$T, ReturnT> finalAsyncResponseTransformer = asyncResponseTransformer",
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/QueryProtocolSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/QueryProtocolSpec.java
index daef19b9def3..f14efae69473 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/QueryProtocolSpec.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/QueryProtocolSpec.java
@@ -28,6 +28,7 @@
import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
import software.amazon.awssdk.codegen.model.intermediate.OperationModel;
import software.amazon.awssdk.codegen.poet.PoetExtension;
+import software.amazon.awssdk.codegen.poet.auth.scheme.AuthSchemeSpecUtils;
import software.amazon.awssdk.codegen.poet.client.traits.HttpChecksumRequiredTrait;
import software.amazon.awssdk.codegen.poet.client.traits.HttpChecksumTrait;
import software.amazon.awssdk.codegen.poet.client.traits.NoneAuthTypeRequestTrait;
@@ -42,10 +43,12 @@ public class QueryProtocolSpec implements ProtocolSpec {
protected final PoetExtension poetExtensions;
protected final IntermediateModel intermediateModel;
+ protected final boolean useSraAuth;
public QueryProtocolSpec(IntermediateModel intermediateModel, PoetExtension poetExtensions) {
this.intermediateModel = intermediateModel;
this.poetExtensions = poetExtensions;
+ this.useSraAuth = new AuthSchemeSpecUtils(intermediateModel).useSraAuth();
}
@Override
@@ -113,13 +116,17 @@ public CodeBlock executionHandler(OperationModel opModel) {
.add(hostPrefixExpression(opModel))
.add(discoveredEndpoint(opModel))
.add(credentialType(opModel, intermediateModel))
+ .add(".withRequestConfiguration(clientConfiguration)")
.add(".withInput($L)", opModel.getInput().getVariableName())
.add(".withMetricCollector(apiCallMetricCollector)")
.add(HttpChecksumRequiredTrait.putHttpChecksumAttribute(opModel))
- .add(HttpChecksumTrait.create(opModel))
- .add(NoneAuthTypeRequestTrait.create(opModel))
- .add(RequestCompressionTrait.create(opModel, intermediateModel));
+ .add(HttpChecksumTrait.create(opModel));
+ if (!useSraAuth) {
+ codeBlock.add(NoneAuthTypeRequestTrait.create(opModel));
+ }
+
+ codeBlock.add(RequestCompressionTrait.create(opModel, intermediateModel));
if (opModel.hasStreamingInput()) {
return codeBlock.add(".withRequestBody(requestBody)")
@@ -150,12 +157,16 @@ public CodeBlock asyncExecutionHandler(IntermediateModel intermediateModel, Oper
.add(".withResponseHandler(responseHandler)\n")
.add(".withErrorResponseHandler(errorResponseHandler)\n")
.add(credentialType(opModel, intermediateModel))
+ .add(".withRequestConfiguration(clientConfiguration)")
.add(".withMetricCollector(apiCallMetricCollector)\n")
.add(HttpChecksumRequiredTrait.putHttpChecksumAttribute(opModel))
- .add(HttpChecksumTrait.create(opModel))
- .add(NoneAuthTypeRequestTrait.create(opModel))
- .add(RequestCompressionTrait.create(opModel, intermediateModel));
+ .add(HttpChecksumTrait.create(opModel));
+
+ if (!useSraAuth) {
+ builder.add(NoneAuthTypeRequestTrait.create(opModel));
+ }
+ builder.add(RequestCompressionTrait.create(opModel, intermediateModel));
builder.add(hostPrefixExpression(opModel) + asyncRequestBody + ".withInput($L)$L);",
opModel.getInput().getVariableName(),
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/XmlProtocolSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/XmlProtocolSpec.java
index 3f58b49edc7b..f7092ccdaf36 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/XmlProtocolSpec.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/XmlProtocolSpec.java
@@ -133,12 +133,16 @@ public CodeBlock executionHandler(OperationModel opModel) {
hostPrefixExpression(opModel) +
discoveredEndpoint(opModel))
.add(credentialType(opModel, model))
+ .add(".withRequestConfiguration(clientConfiguration)")
.add(".withInput($L)", opModel.getInput().getVariableName())
.add(HttpChecksumRequiredTrait.putHttpChecksumAttribute(opModel))
- .add(HttpChecksumTrait.create(opModel))
- .add(NoneAuthTypeRequestTrait.create(opModel))
- .add(RequestCompressionTrait.create(opModel, model));
+ .add(HttpChecksumTrait.create(opModel));
+ if (!useSraAuth) {
+ codeBlock.add(NoneAuthTypeRequestTrait.create(opModel));
+ }
+
+ codeBlock.add(RequestCompressionTrait.create(opModel, model));
s3ArnableFields(opModel, model).ifPresent(codeBlock::add);
@@ -195,11 +199,11 @@ public CodeBlock asyncExecutionHandler(IntermediateModel intermediateModel, Oper
if (opModel.hasEventStreamOutput()) {
executionResponseTransformerName = "restAsyncResponseTransformer";
}
-
builder.add("\n\n$T<$T> executeFuture = clientHandler.execute(new $T<$T, $T>()\n",
CompletableFuture.class, executeFutureValueType,
ClientExecutionParams.class, requestType, pojoResponseType)
.add(".withOperationName(\"$N\")\n", opModel.getOperationName())
+ .add(".withRequestConfiguration(clientConfiguration)")
.add(".withMarshaller($L)\n", asyncMarshaller(intermediateModel, opModel, marshaller, "protocolFactory"));
if (opModel.hasEventStreamOutput()) {
@@ -214,9 +218,13 @@ public CodeBlock asyncExecutionHandler(IntermediateModel intermediateModel, Oper
.add(".withMetricCollector(apiCallMetricCollector)\n")
.add(asyncRequestBody(opModel))
.add(HttpChecksumRequiredTrait.putHttpChecksumAttribute(opModel))
- .add(HttpChecksumTrait.create(opModel))
- .add(NoneAuthTypeRequestTrait.create(opModel))
- .add(RequestCompressionTrait.create(opModel, model));
+ .add(HttpChecksumTrait.create(opModel));
+
+ if (!useSraAuth) {
+ builder.add(NoneAuthTypeRequestTrait.create(opModel));
+ }
+
+ builder.add(RequestCompressionTrait.create(opModel, model));
s3ArnableFields(opModel, model).ifPresent(builder::add);
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/model/SdkClientConfigurationUtilGeneratorTask.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/model/SdkClientConfigurationUtilGeneratorTask.java
new file mode 100644
index 000000000000..46b9f0233212
--- /dev/null
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/model/SdkClientConfigurationUtilGeneratorTask.java
@@ -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 software.amazon.awssdk.codegen.poet.model;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UncheckedIOException;
+import java.util.Collections;
+import java.util.List;
+import software.amazon.awssdk.codegen.emitters.GeneratorTask;
+import software.amazon.awssdk.codegen.emitters.GeneratorTaskParams;
+import software.amazon.awssdk.codegen.emitters.SimpleGeneratorTask;
+import software.amazon.awssdk.codegen.emitters.tasks.BaseGeneratorTasks;
+import software.amazon.awssdk.utils.IoUtils;
+
+public final class SdkClientConfigurationUtilGeneratorTask extends BaseGeneratorTasks {
+ public static final String RUNTIME_CLASS_NAME = "SdkClientConfigurationUtil";
+
+ private final String internalPackage;
+ private final String internalClassDir;
+ private final String fileHeader;
+ private final String runtimeClassCode;
+
+ public SdkClientConfigurationUtilGeneratorTask(GeneratorTaskParams generatorTaskParams) {
+ super(generatorTaskParams);
+ this.internalPackage = model.getMetadata().getFullClientInternalPackageName();
+ this.internalClassDir = generatorTaskParams.getPathProvider().getClientInternalDirectory();
+ this.fileHeader = generatorTaskParams.getModel().getFileHeader();
+ this.runtimeClassCode = loadConfigUtilCode();
+ }
+
+ @Override
+ protected List createTasks() throws Exception {
+ String codeContents =
+ "package " + internalPackage + ";\n" +
+ "\n"
+ + runtimeClassCode;
+
+ String fileName = RUNTIME_CLASS_NAME + ".java";
+ return Collections.singletonList(new SimpleGeneratorTask(internalClassDir, fileName, fileHeader,
+ () -> codeContents));
+ }
+
+ private static String loadConfigUtilCode() {
+ try {
+ InputStream is = SdkClientConfigurationUtilGeneratorTask.class.getResourceAsStream(
+ "/software/amazon/awssdk/codegen/poet/model/SdkClientConfigurationUtil.resource.java");
+ return IoUtils.toUtf8String(is);
+ } catch (IOException ioe) {
+ throw new UncheckedIOException(ioe);
+ }
+ }
+}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/model/ServiceClientConfigurationBuilderClass.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/model/ServiceClientConfigurationBuilderClass.java
new file mode 100644
index 000000000000..d73b58de43e0
--- /dev/null
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/model/ServiceClientConfigurationBuilderClass.java
@@ -0,0 +1,249 @@
+/*
+ * 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.codegen.poet.model;
+
+import static javax.lang.model.element.Modifier.ABSTRACT;
+import static javax.lang.model.element.Modifier.FINAL;
+import static javax.lang.model.element.Modifier.PRIVATE;
+import static javax.lang.model.element.Modifier.PUBLIC;
+import static javax.lang.model.element.Modifier.STATIC;
+import static software.amazon.awssdk.codegen.poet.model.ServiceClientConfigurationUtils.Field;
+
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.MethodSpec;
+import com.squareup.javapoet.TypeSpec;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+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.core.client.config.SdkClientConfiguration;
+import software.amazon.awssdk.utils.Validate;
+
+public class ServiceClientConfigurationBuilderClass implements ClassSpec {
+ private final ServiceClientConfigurationUtils utils;
+ private final ClassName builderInterface;
+
+ public ServiceClientConfigurationBuilderClass(IntermediateModel model) {
+ this.utils = new ServiceClientConfigurationUtils(model);
+ this.builderInterface = utils.serviceClientConfigurationClassName().nestedClass("Builder");
+ }
+
+ @Override
+ public ClassName className() {
+ return utils.serviceClientConfigurationBuilderClassName();
+ }
+
+ @Override
+ public TypeSpec poetSpec() {
+ TypeSpec.Builder builder = PoetUtils.createClassBuilder(className())
+ .addModifiers(PUBLIC)
+ .addAnnotation(SdkInternalApi.class);
+
+ return builder.addMethod(builderMethod())
+ .addMethod(builderFromSdkClientConfiguration())
+ .addType(builderInternalSpec())
+ .addType(builderImplSpec())
+ .build();
+ }
+
+
+ private MethodSpec builderFromSdkClientConfiguration() {
+ return MethodSpec.methodBuilder("builder")
+ .addModifiers(PUBLIC, STATIC)
+ .addParameter(SdkClientConfiguration.Builder.class, "builder")
+ .returns(className().nestedClass("BuilderInternal"))
+ .addStatement("return new BuilderImpl(builder)")
+ .build();
+ }
+
+
+ private MethodSpec builderMethod() {
+ return MethodSpec.methodBuilder("builder")
+ .addModifiers(PUBLIC, STATIC)
+ .returns(builderInterface)
+ .addStatement("return new BuilderImpl()")
+ .build();
+ }
+
+ private TypeSpec builderInternalSpec() {
+ TypeSpec.Builder builder = TypeSpec.interfaceBuilder("BuilderInternal")
+ .addModifiers(PUBLIC)
+ .addSuperinterface(builderInterface);
+ builder.addMethod(MethodSpec.methodBuilder("buildSdkClientConfiguration")
+ .addModifiers(PUBLIC, ABSTRACT)
+ .returns(SdkClientConfiguration.class)
+ .build());
+ return builder.build();
+ }
+
+ private TypeSpec builderImplSpec() {
+ TypeSpec.Builder builder = TypeSpec.classBuilder("BuilderImpl")
+ .addModifiers(PUBLIC, STATIC)
+ .addSuperinterface(className().nestedClass("BuilderInternal"));
+
+ builder.addField(SdkClientConfiguration.Builder.class, "internalBuilder", PRIVATE, FINAL);
+
+ builder.addMethod(MethodSpec.constructorBuilder()
+ .addModifiers(PRIVATE)
+ .addStatement("this.internalBuilder = $T.builder()", SdkClientConfiguration.class)
+ .build());
+ builder.addMethod(constructorFromSdkClientConfiguration());
+
+ for (Field field : utils.serviceClientConfigurationFields()) {
+ addLocalFieldForBuilderIfNeeded(field, builder);
+ builder.addMethod(setterForField(field));
+ builder.addMethod(getterForBuilderField(field));
+ }
+
+ builder.addMethod(MethodSpec.methodBuilder("build")
+ .addAnnotation(Override.class)
+ .addModifiers(PUBLIC)
+ .returns(utils.serviceClientConfigurationClassName())
+ .addStatement("return new $T(this)", utils.serviceClientConfigurationClassName())
+ .build());
+
+ builder.addMethod(buildSdkClientConfigurationMethod());
+
+ return builder.build();
+ }
+
+ private MethodSpec buildSdkClientConfigurationMethod() {
+ MethodSpec.Builder builder = MethodSpec.methodBuilder("buildSdkClientConfiguration")
+ .addModifiers(PUBLIC)
+ .addAnnotation(Override.class)
+ .returns(SdkClientConfiguration.class);
+
+ for (Field field : utils.serviceClientConfigurationFields()) {
+ if (field.optionClass() == null) {
+ CodeBlock block = field.copyToConfiguration();
+ if (block != null) {
+ builder.addCode(block);
+ }
+ }
+ }
+ return builder
+ .addStatement("return internalBuilder.build()")
+ .build();
+ }
+
+ private MethodSpec constructorFromSdkClientConfiguration() {
+ MethodSpec.Builder builder = MethodSpec.constructorBuilder()
+ .addModifiers(PRIVATE)
+ .addParameter(SdkClientConfiguration.Builder.class, "internalBuilder")
+ .addStatement("this.internalBuilder = internalBuilder");
+
+ for (Field field : utils.serviceClientConfigurationFields()) {
+ if (field.optionClass() == null) {
+ CodeBlock block = field.constructFromConfiguration();
+ if (block != null) {
+ builder.addCode(block);
+ }
+ }
+ }
+ return builder.build();
+ }
+
+
+ private void addLocalFieldForBuilderIfNeeded(Field field, TypeSpec.Builder builder) {
+ if (field.optionClass() == null) {
+ builder.addField(field.type(), field.name(), PRIVATE);
+ }
+ }
+
+ private MethodSpec setterForField(Field field) {
+ MethodSpec fieldBuilderSetter = field.builderSetterImpl();
+ if (fieldBuilderSetter != null) {
+ return fieldBuilderSetter.toBuilder().returns(builderInterface).build();
+ }
+ MethodSpec.Builder builder = baseSetterForField(field);
+ if (field.isLocalField()) {
+ builder.addAnnotation(Override.class);
+ }
+ if (field.optionClass() == null) {
+ return builder.addStatement("this.$1L = $1L", field.name())
+ .addStatement("return this")
+ .build();
+
+ }
+ return builder.addStatement("internalBuilder.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(builderInterface);
+ if (!field.isLocalField()) {
+ builder.addAnnotation(Override.class);
+ }
+ return builder;
+ }
+
+ private MethodSpec getterForBuilderField(Field field) {
+ return getterForField(field, "internalBuilder", false);
+ }
+
+
+ private MethodSpec getterForField(Field field, String fieldName, boolean forDataGetter) {
+ MethodSpec fieldBuilderGetter = field.builderGetterImpl();
+ if (fieldBuilderGetter != null) {
+ return fieldBuilderGetter.toBuilder()
+ .returns(field.type())
+ .build();
+ }
+ MethodSpec.Builder builder = baseGetterForField(field);
+ if (!forDataGetter && field.isLocalField()) {
+ builder.addAnnotation(Override.class);
+ }
+ if (forDataGetter && field.isLocalField()) {
+ return builder.addStatement("return $L", field.name())
+ .build();
+ }
+ if (field.optionClass() == null) {
+ return builder.addStatement("return $L", field.name())
+ .build();
+ }
+ if (field.baseType() != null) {
+ return builder.addStatement("$T result = $L.option($T.$L)",
+ field.baseType(), fieldName, 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 $L.option($T.$L)", fieldName, 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.isLocalField()) {
+ builder.addAnnotation(Override.class);
+ }
+ return builder;
+ }
+}
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..14f63bc3b9ed 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
@@ -20,158 +20,172 @@
import static javax.lang.model.element.Modifier.PRIVATE;
import static javax.lang.model.element.Modifier.PUBLIC;
import static javax.lang.model.element.Modifier.STATIC;
+import static software.amazon.awssdk.codegen.poet.model.ServiceClientConfigurationUtils.Field;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.TypeSpec;
-import java.net.URI;
import software.amazon.awssdk.annotations.SdkPublicApi;
import software.amazon.awssdk.awscore.AwsServiceClientConfiguration;
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.core.client.config.ClientOverrideConfiguration;
-import software.amazon.awssdk.endpoints.EndpointProvider;
-import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.utils.Validate;
public class ServiceClientConfigurationClass implements ClassSpec {
private final ClassName defaultClientMetadataClassName;
+ private final ServiceClientConfigurationUtils utils;
public ServiceClientConfigurationClass(IntermediateModel model) {
String basePackage = model.getMetadata().getFullClientPackageName();
String serviceId = model.getMetadata().getServiceName();
this.defaultClientMetadataClassName = ClassName.get(basePackage, serviceId + "ServiceClientConfiguration");
+ this.utils = new ServiceClientConfigurationUtils(model);
}
@Override
- public TypeSpec poetSpec() {
- return PoetUtils.createClassBuilder(defaultClientMetadataClassName)
- .superclass(AwsServiceClientConfiguration.class)
- .addJavadoc("Class to expose the service client settings to the user. Implementation of {@link $T}",
- AwsServiceClientConfiguration.class)
- .addMethod(constructor())
- .addMethod(builderMethod())
- .addModifiers(PUBLIC, FINAL)
- .addAnnotation(SdkPublicApi.class)
- .addType(builderInterfaceSpec())
- .addType(builderImplSpec())
- .build();
+ public ClassName className() {
+ return utils.serviceClientConfigurationClassName();
}
@Override
- public ClassName className() {
- return defaultClientMetadataClassName;
+ public TypeSpec poetSpec() {
+ TypeSpec.Builder builder = PoetUtils.createClassBuilder(defaultClientMetadataClassName)
+ .addModifiers(PUBLIC, FINAL)
+ .addAnnotation(SdkPublicApi.class)
+ .superclass(AwsServiceClientConfiguration.class)
+ .addJavadoc("Class to expose the service client settings to the user. "
+ + "Implementation of {@link $T}",
+ AwsServiceClientConfiguration.class);
+
+ builder.addMethod(constructor());
+ for (Field field : utils.serviceClientConfigurationFields()) {
+ addLocalFieldForDataIfNeeded(field, builder);
+ if (field.isLocalField()) {
+ builder.addMethod(getterForDataField(field));
+ }
+ }
+
+ return builder.addMethod(builderMethod())
+ .addType(builderInterfaceSpec())
+ .build();
}
- public MethodSpec constructor() {
- return MethodSpec.constructorBuilder()
- .addModifiers(PRIVATE)
- .addParameter(className().nestedClass("Builder"), "builder")
- .addStatement("super(builder)")
- .build();
+ private MethodSpec constructor() {
+ MethodSpec.Builder builder = MethodSpec.constructorBuilder()
+ .addModifiers(PUBLIC)
+ .addParameter(className().nestedClass("Builder"), "builder");
+ builder.addStatement("super(builder)");
+ for (Field field : utils.serviceClientConfigurationFields()) {
+ if (field.isLocalField()) {
+ builder.addStatement("this.$L = builder.$L()", field.name(), field.name());
+ }
+ }
+ return builder.build();
}
- public MethodSpec builderMethod() {
+ private MethodSpec builderMethod() {
return MethodSpec.methodBuilder("builder")
.addModifiers(PUBLIC, STATIC)
- .addStatement("return new BuilderImpl()")
+ .addStatement("return $T.builder()",
+ utils.serviceClientConfigurationBuilderClassName())
.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 : utils.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 void addLocalFieldForDataIfNeeded(Field field, TypeSpec.Builder builder) {
+ if (field.isLocalField()) {
+ builder.addField(field.type(), field.name(), PRIVATE, FINAL);
+ }
+ }
+
+ private MethodSpec.Builder baseSetterForField(Field field) {
+ MethodSpec fieldBuilderSetter = field.builderSetter();
+ if (fieldBuilderSetter != null) {
+ return fieldBuilderSetter.toBuilder()
+ .returns(className().nestedClass("Builder"));
+ }
+
+ 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.isLocalField()) {
+ builder.addAnnotation(Override.class);
+ }
+ return builder;
+ }
+
+ private MethodSpec getterForDataField(Field field) {
+ return getterForField(field, "config", true);
+ }
+
+ private MethodSpec getterForField(Field field, String fieldName, boolean forDataGetter) {
+ MethodSpec fieldBuilderGetter = field.builderGetterImpl();
+ if (fieldBuilderGetter != null) {
+ return fieldBuilderGetter.toBuilder()
+ .returns(field.type())
+ .build();
+ }
+
+ MethodSpec.Builder builder = baseGetterForField(field);
+ if (!forDataGetter && field.isLocalField()) {
+ builder.addAnnotation(Override.class);
+ }
+ if (forDataGetter && field.isLocalField()) {
+ return builder.addStatement("return $L", field.name())
+ .build();
+ }
+ if (field.optionClass() == null) {
+ return builder.addStatement("return $L", field.name())
+ .build();
+ }
+ if (field.baseType() != null) {
+ return builder.addStatement("$T result = $L.option($T.$L)",
+ field.baseType(), fieldName, 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 $L.option($T.$L)", fieldName, field.optionClass(), field.optionName())
+ .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();
+ 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.isLocalField()) {
+ builder.addAnnotation(Override.class);
+ }
+ return builder;
}
}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/model/ServiceClientConfigurationUtils.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/model/ServiceClientConfigurationUtils.java
new file mode 100644
index 000000000000..6e2d33f15ae5
--- /dev/null
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/model/ServiceClientConfigurationUtils.java
@@ -0,0 +1,508 @@
+/*
+ * 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.codegen.poet.model;
+
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.MethodSpec;
+import com.squareup.javapoet.ParameterizedTypeName;
+import com.squareup.javapoet.TypeName;
+import com.squareup.javapoet.WildcardTypeName;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.lang.model.element.Modifier;
+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.auth.scheme.AuthSchemeSpecUtils;
+import software.amazon.awssdk.core.SdkServiceClientConfiguration;
+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.endpoints.EndpointProvider;
+import software.amazon.awssdk.http.auth.spi.scheme.AuthScheme;
+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.identity.spi.IdentityProviders;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.utils.Validate;
+
+public class ServiceClientConfigurationUtils {
+ private static final List BASE_FIELDS = baseServiceClientConfigurationFields();
+ private final AuthSchemeSpecUtils authSchemeSpecUtils;
+ private final ClassName configurationClassName;
+ private final ClassName configurationBuilderClassName;
+ private final ClassName sdkClientConfigurationUtilClassName;
+
+ public ServiceClientConfigurationUtils(IntermediateModel model) {
+ String basePackage = model.getMetadata().getFullClientPackageName();
+ String serviceId = model.getMetadata().getServiceName();
+ configurationClassName = ClassName.get(basePackage, serviceId + "ServiceClientConfiguration");
+ configurationBuilderClassName = ClassName.get(model.getMetadata().getFullClientInternalPackageName(),
+ serviceId + "ServiceClientConfigurationBuilder");
+ sdkClientConfigurationUtilClassName = ClassName.get(model.getMetadata().getFullClientInternalPackageName(),
+ "SdkClientConfigurationUtil");
+ authSchemeSpecUtils = new AuthSchemeSpecUtils(model);
+
+ }
+
+ /**
+ * Returns the {@link ClassName} of the service client configuration class.
+ */
+ public ClassName serviceClientConfigurationClassName() {
+ return configurationClassName;
+ }
+
+ /**
+ * Returns the {@link ClassName} of the builder for the service client configuration class.
+ */
+ public ClassName serviceClientConfigurationBuilderClassName() {
+ return configurationBuilderClassName;
+ }
+
+ /**
+ * Returns the list of fields present in the service client configuration class with its corresponding {@link ClientOption}
+ * mapping to the {@link SdkClientConfiguration} class.
+ */
+ public List serviceClientConfigurationFields() {
+ List fields = new ArrayList<>();
+ fields.add(overrideConfigurationField());
+ fields.addAll(BASE_FIELDS);
+ fields.add(Field.builder("authSchemeProvider", authSchemeSpecUtils.providerInterfaceName())
+ .doc("auth scheme provider")
+ .optionClass(SdkClientOption.class)
+ .optionValue(SdkClientOption.AUTH_SCHEME_PROVIDER)
+ .baseType(ClassName.get(AuthSchemeProvider.class))
+ .build());
+ return fields;
+ }
+
+ private Field overrideConfigurationField() {
+ Field.Builder builder = Field.builder("overrideConfiguration", ClientOverrideConfiguration.class)
+ .doc("client override configuration")
+ .definingClass(SdkServiceClientConfiguration.class);
+
+ builder.copyToConfiguration(
+ CodeBlock.builder()
+ .beginControlFlow("if (overrideConfiguration != null)")
+ .addStatement("$T.copyOverridesToConfiguration(overrideConfiguration, internalBuilder)",
+ sdkClientConfigurationUtilClassName)
+ .endControlFlow()
+ .build()
+ );
+
+ return builder.build();
+ }
+
+ private static List baseServiceClientConfigurationFields() {
+ return Arrays.asList(
+ endpointOverrideField(),
+ Field.builder("endpointProvider", EndpointProvider.class)
+ .doc("endpoint provider")
+ .definingClass(SdkServiceClientConfiguration.class)
+ .optionClass(SdkClientOption.class)
+ .optionValue(SdkClientOption.ENDPOINT_PROVIDER)
+ .build(),
+ Field.builder("region", Region.class)
+ .doc("AWS region")
+ .definingClass(AwsServiceClientConfiguration.class)
+ .optionClass(AwsClientOption.class)
+ .optionValue(AwsClientOption.AWS_REGION)
+ .build(),
+ credentialsProviderField(),
+ authSchemesField()
+ );
+ }
+
+ private static Field endpointOverrideField() {
+ Field.Builder builder = Field.builder("endpointOverride", URI.class)
+ .doc("endpoint override")
+ .definingClass(SdkServiceClientConfiguration.class);
+ builder.constructFromConfiguration(
+ CodeBlock.builder()
+ .beginControlFlow("if (Boolean.TRUE.equals(internalBuilder.option($T.$L)))",
+ SdkClientOption.class, fieldName(SdkClientOption.ENDPOINT_OVERRIDDEN,
+ SdkClientOption.class))
+ .addStatement("this.endpointOverride = internalBuilder.option($T.$L)",
+ SdkClientOption.class, fieldName(SdkClientOption.ENDPOINT,
+ SdkClientOption.class))
+ .endControlFlow()
+ .build()
+ );
+
+ builder.copyToConfiguration(
+ CodeBlock.builder()
+ .beginControlFlow("if (endpointOverride != null)")
+ .addStatement("internalBuilder.option($T.$L, endpointOverride)",
+ SdkClientOption.class, fieldName(SdkClientOption.ENDPOINT, SdkClientOption.class))
+ .addStatement("internalBuilder.option($T.$L, true)",
+ SdkClientOption.class, fieldName(SdkClientOption.ENDPOINT_OVERRIDDEN, SdkClientOption.class))
+ .endControlFlow()
+ .build()
+ );
+
+ return builder.build();
+ }
+
+ private static Field credentialsProviderField() {
+ Field.Builder builder = Field.builder("credentialsProvider",
+ ParameterizedTypeName.get(ClassName.get(IdentityProvider.class),
+ WildcardTypeName.subtypeOf(AwsCredentialsIdentity.class)))
+ .doc("credentials provider")
+ .definingClass(AwsServiceClientConfiguration.class);
+
+ builder.constructFromConfiguration(
+ CodeBlock.builder()
+ .addStatement("this.credentialsProvider = internalBuilder.option($T.$L)",
+ AwsClientOption.class, fieldName(AwsClientOption.CREDENTIALS_IDENTITY_PROVIDER,
+ AwsClientOption.class))
+ .build()
+ );
+
+ builder.copyToConfiguration(
+ // TODO(sra-plugins)
+ // This code duplicates the logic here
+ // https://github.com/aws/aws-sdk-java-v2/blob/fa9dbcce47637486e3f7d4d366ab6509b535342a/core/aws-core/src/main/java/software/amazon/awssdk/awscore/client/builder/AwsDefaultClientBuilder.java#L212
+ // That adds the credentialsProvider to the identityProviders class. This is for request level plugins,
+ // to be able to support credentialsProvider overrides.
+ CodeBlock.builder()
+ .beginControlFlow("if (credentialsProvider != null &&"
+ + " !credentialsProvider.equals(internalBuilder.option($T.$L)))",
+ AwsClientOption.class, fieldName(AwsClientOption.CREDENTIALS_IDENTITY_PROVIDER,
+ AwsClientOption.class))
+ .addStatement("internalBuilder.option($T.$L, credentialsProvider)",
+ AwsClientOption.class, fieldName(AwsClientOption.CREDENTIALS_IDENTITY_PROVIDER,
+ AwsClientOption.class))
+ .addStatement("$T identityProviders = internalBuilder.option($T.$L)",
+ IdentityProviders.class, SdkClientOption.class,
+ fieldName(SdkClientOption.IDENTITY_PROVIDERS, SdkClientOption.class))
+ .beginControlFlow("if (identityProviders == null)")
+ .addStatement("identityProviders = $T.builder().putIdentityProvider(credentialsProvider).build()",
+ IdentityProviders.class)
+ .nextControlFlow(" else ")
+ .addStatement("identityProviders = identityProviders.toBuilder()"
+ + ".putIdentityProvider(credentialsProvider)"
+ + ".build()")
+ .endControlFlow()
+ .addStatement("internalBuilder.option($T.$L, identityProviders)",
+ SdkClientOption.class, fieldName(SdkClientOption.IDENTITY_PROVIDERS, SdkClientOption.class))
+ .endControlFlow()
+ .build()
+ );
+
+ return builder.build();
+ }
+
+
+ private static Field authSchemesField() {
+ TypeName authSchemeGenericType = ParameterizedTypeName.get(ClassName.get(AuthScheme.class),
+ WildcardTypeName.subtypeOf(Object.class));
+ TypeName authSchemesType = ParameterizedTypeName.get(ClassName.get(Map.class), ClassName.get(String.class),
+ authSchemeGenericType);
+ Field.Builder builder = Field.builder("authSchemes",
+ authSchemesType)
+ .doc("auth schemes")
+ .definingClass(SdkServiceClientConfiguration.class);
+
+ builder.constructFromConfiguration(
+ CodeBlock.builder()
+ .addStatement("$T authSchemes = internalBuilder.option($T.$L)",
+ authSchemesType, SdkClientOption.class,
+ fieldName(SdkClientOption.AUTH_SCHEMES, SdkClientOption.class))
+ .beginControlFlow("if (authSchemes != null)")
+ .addStatement("authSchemes = new $T<>(authSchemes)", HashMap.class)
+ .endControlFlow()
+ .addStatement("this.authSchemes = authSchemes")
+ .build()
+ );
+
+ builder.copyToConfiguration(
+ CodeBlock.builder()
+ .beginControlFlow("if (authSchemes != null &&"
+ + " !authSchemes.equals(internalBuilder.option($T.$L)))",
+ SdkClientOption.class, fieldName(SdkClientOption.AUTH_SCHEMES,
+ SdkClientOption.class))
+ .addStatement("internalBuilder.option($T.$L, authSchemes())",
+ SdkClientOption.class, fieldName(SdkClientOption.AUTH_SCHEMES,
+ SdkClientOption.class))
+ .endControlFlow()
+ .build()
+ );
+
+ builder.builderSetterImpl(
+ MethodSpec.methodBuilder("putAuthScheme")
+ .addModifiers(Modifier.PUBLIC)
+ .addAnnotation(Override.class)
+ .addParameter(authSchemeGenericType, "authScheme")
+ .beginControlFlow("if (authSchemes == null)")
+ .addStatement("authSchemes = new $T<>()", HashMap.class)
+ .endControlFlow()
+ .addStatement("authSchemes.put(authScheme.schemeId(), authScheme)")
+ .addStatement("return this")
+ .build()
+ );
+
+ builder.builderSetter(
+ MethodSpec.methodBuilder("putAuthScheme")
+ .addModifiers(Modifier.PUBLIC)
+ .addAnnotation(Override.class)
+ .addParameter(authSchemeGenericType, "authScheme")
+ .build()
+ );
+
+ builder.builderGetterImpl(
+ MethodSpec.methodBuilder("authSchemes")
+ .addModifiers(Modifier.PUBLIC)
+ .addAnnotation(Override.class)
+ .returns(authSchemesType)
+ .beginControlFlow("if (authSchemes == null)")
+ .addStatement("return $T.emptyMap()", Collections.class)
+ .endControlFlow()
+ .addStatement("return $T.unmodifiableMap(new $T<>(authSchemes))", Collections.class, HashMap.class)
+ .build()
+ );
+
+ return builder.build();
+ }
+
+ static class Field {
+ private final String name;
+ private final TypeName type;
+ private final Class extends SdkServiceClientConfiguration> definingClass;
+ private final Class extends ClientOption> optionClass;
+ private final String optionName;
+ private final String doc;
+ private final TypeName baseType;
+ private final CodeBlock constructFromConfiguration;
+ private final CodeBlock copyToConfiguration;
+ private final MethodSpec builderSetterImpl;
+ private final MethodSpec builderSetter;
+ private final MethodSpec builderGetterImpl;
+
+ Field(Field.Builder builder) {
+ this.name = Validate.paramNotNull(builder.name, "name");
+ this.type = Validate.paramNotNull(builder.type, "type");
+ this.definingClass = builder.definingClass;
+ this.doc = Validate.paramNotNull(builder.doc, "doc");
+ this.optionClass = builder.optionClass;
+ this.optionName = builder.optionName;
+ this.baseType = builder.baseType;
+ this.constructFromConfiguration = builder.constructFromConfiguration;
+ this.copyToConfiguration = builder.copyToConfiguration;
+ this.builderSetterImpl = builder.builderSetterImpl;
+ this.builderSetter = builder.builderSetter;
+ this.builderGetterImpl = builder.builderGetterImpl;
+ }
+
+ public boolean isLocalField() {
+ return definingClass == null;
+ }
+
+ public String name() {
+ return name;
+ }
+
+ public TypeName type() {
+ return type;
+ }
+
+ public Class extends SdkServiceClientConfiguration> definingClass() {
+ return definingClass;
+ }
+
+ public Class extends ClientOption> optionClass() {
+ return optionClass;
+ }
+
+ public String optionName() {
+ return optionName;
+ }
+
+ public String doc() {
+ return doc;
+ }
+
+ public TypeName baseType() {
+ return baseType;
+ }
+
+ public CodeBlock constructFromConfiguration() {
+ return constructFromConfiguration;
+ }
+
+ public CodeBlock copyToConfiguration() {
+ return copyToConfiguration;
+ }
+
+ public MethodSpec builderSetterImpl() {
+ return builderSetterImpl;
+ }
+
+ public MethodSpec builderSetter() {
+ return builderSetter;
+ }
+
+ public MethodSpec builderGetterImpl() {
+ return builderGetterImpl;
+ }
+
+ public static Field.Builder builder() {
+ return new Field.Builder();
+ }
+
+ public static Field.Builder builder(String name, TypeName type) {
+ return new Field.Builder()
+ .name(name)
+ .type(type);
+ }
+
+ public static Field.Builder builder(String name, Class> type) {
+ return new Field.Builder()
+ .name(name)
+ .type(type);
+ }
+
+ static class Builder {
+ private String name;
+ private TypeName type;
+ private String doc;
+ private Class extends SdkServiceClientConfiguration> definingClass;
+ private Class extends ClientOption> optionClass;
+ private ClientOption> value;
+ private String optionName;
+ private TypeName baseType;
+ private CodeBlock constructFromConfiguration;
+ private CodeBlock copyToConfiguration;
+ private MethodSpec builderSetterImpl;
+ private MethodSpec builderSetter;
+ private MethodSpec builderGetterImpl;
+
+ 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 extends ClientOption> optionClass) {
+ this.optionClass = optionClass;
+ return this;
+ }
+
+ public Field.Builder optionValue(ClientOption> value) {
+ this.value = value;
+ return this;
+ }
+
+ public Field.Builder baseType(TypeName baseType) {
+ this.baseType = baseType;
+ return this;
+ }
+
+ public Field.Builder definingClass(Class extends SdkServiceClientConfiguration> definingClass) {
+ this.definingClass = definingClass;
+ return this;
+ }
+
+ public Field.Builder constructFromConfiguration(CodeBlock constructFromConfiguration) {
+ this.constructFromConfiguration = constructFromConfiguration;
+ return this;
+ }
+
+ public Field.Builder copyToConfiguration(CodeBlock copyToConfiguration) {
+ this.copyToConfiguration = copyToConfiguration;
+ return this;
+ }
+
+ public Field.Builder builderSetterImpl(MethodSpec builderSetter) {
+ this.builderSetterImpl = builderSetter;
+ return this;
+ }
+
+ public Field.Builder builderSetter(MethodSpec builderSetter) {
+ this.builderSetter = builderSetter;
+ return this;
+ }
+
+ public Field.Builder builderGetterImpl(MethodSpec builderGetterImpl) {
+ this.builderGetterImpl = builderGetterImpl;
+ return this;
+ }
+
+ public Field build() {
+ if (value != null && optionClass != null) {
+ optionName = fieldName(value, optionClass);
+ }
+ return new Field(this);
+ }
+ }
+ }
+
+ /**
+ * This method resolves an static reference to its name, for instance, when called with
+ *
+ * fieldName(AwsClientOption.AWS_REGION, AwsClientOption.class)
+ *
+ * it will return the string "AWS_REGION" that we can use for codegen. Using the value directly avoid typo bugs and allows the
+ * compiler and the IDE to know about this relationship.
+ *
+ * This method uses the fully qualified names in the reflection package to avoid polluting this class imports. Adapted from
+ * https://stackoverflow.com/a/35416606
+ */
+ private static String fieldName(Object fieldObject, Class> parent) {
+ java.lang.reflect.Field[] allFields = parent.getFields();
+ for (java.lang.reflect.Field field : allFields) {
+ int modifiers = field.getModifiers();
+ if (!java.lang.reflect.Modifier.isStatic(modifiers)) {
+ continue;
+ }
+ Object currentFieldObject;
+ try {
+ // For static fields you can pass a null to get back its value.
+ currentFieldObject = field.get(null);
+ } catch (Exception e) {
+ throw new IllegalArgumentException(e);
+ }
+ boolean isWantedField = fieldObject.equals(currentFieldObject);
+ if (isWantedField) {
+ return field.getName();
+ }
+ }
+ throw new java.util.NoSuchElementException(String.format("cannot find constant %s in class %s",
+ fieldObject,
+ parent.getClass().getName()));
+ }
+}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointAuthSchemeInterceptorClassSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointAuthSchemeInterceptorClassSpec.java
deleted file mode 100644
index 8d35223c1e85..000000000000
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointAuthSchemeInterceptorClassSpec.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * 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.codegen.poet.rules;
-
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.ParameterizedTypeName;
-import com.squareup.javapoet.TypeSpec;
-import java.util.List;
-import java.util.function.Supplier;
-import javax.lang.model.element.Modifier;
-import software.amazon.awssdk.annotations.SdkInternalApi;
-import software.amazon.awssdk.auth.signer.Aws4Signer;
-import software.amazon.awssdk.auth.signer.AwsS3V4Signer;
-import software.amazon.awssdk.auth.signer.SignerLoader;
-import software.amazon.awssdk.awscore.AwsRequest;
-import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute;
-import software.amazon.awssdk.awscore.endpoints.authscheme.EndpointAuthScheme;
-import software.amazon.awssdk.awscore.util.SignerOverrideUtils;
-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.core.SdkRequest;
-import software.amazon.awssdk.core.exception.SdkClientException;
-import software.amazon.awssdk.core.interceptor.Context;
-import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
-import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
-import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute;
-import software.amazon.awssdk.core.signer.Signer;
-import software.amazon.awssdk.endpoints.Endpoint;
-
-/**
- * Generates the Endpoint Interceptor responsible for applying the {@link AwsEndpointAttribute#AUTH_SCHEMES} property on the
- * endpoint if they exist. Auth schemes describe auth related requirements for the endpoint, such as signing name, signing
- * region, and the name of the auth scheme to use, such as SigV4.
- */
-public class EndpointAuthSchemeInterceptorClassSpec implements ClassSpec {
- private static final String SIGV4_NAME = "sigv4";
- private static final String SIGV4A_NAME = "sigv4a";
-
- private final EndpointRulesSpecUtils endpointRulesSpecUtils;
-
- public EndpointAuthSchemeInterceptorClassSpec(IntermediateModel intermediateModel) {
- this.endpointRulesSpecUtils = new EndpointRulesSpecUtils(intermediateModel);
- }
-
- @Override
- public TypeSpec poetSpec() {
- TypeSpec.Builder b = PoetUtils.createClassBuilder(className())
- .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
- .addAnnotation(SdkInternalApi.class)
- .addSuperinterface(ExecutionInterceptor.class);
-
- b.addMethod(modifyRequestMethod());
- b.addMethod(signerProviderMethod());
-
- return b.build();
- }
-
- @Override
- public ClassName className() {
- return endpointRulesSpecUtils.authSchemesInterceptorName();
- }
-
- private MethodSpec modifyRequestMethod() {
- MethodSpec.Builder builder = MethodSpec.methodBuilder("modifyRequest")
- .addModifiers(Modifier.PUBLIC)
- .addAnnotation(Override.class)
- .addParameter(ClassName.get(Context.ModifyRequest.class), "context")
- .addParameter(ExecutionAttributes.class, "executionAttributes")
- .returns(SdkRequest.class);
-
- builder.addStatement("$T resolvedEndpoint = executionAttributes.getAttribute($T.RESOLVED_ENDPOINT)", Endpoint.class,
- SdkInternalExecutionAttribute.class);
-
- builder.addStatement("$1T request = ($1T) context.request()", AwsRequest.class);
-
- builder.beginControlFlow("if (resolvedEndpoint.headers() != null)")
- .addStatement("request = $T.addHeaders(request, resolvedEndpoint.headers())",
- endpointRulesSpecUtils.rulesRuntimeClassName("AwsEndpointProviderUtils"));
- builder.endControlFlow();
-
- builder.addStatement("$T authSchemes = resolvedEndpoint.attribute($T.AUTH_SCHEMES)",
- ParameterizedTypeName.get(List.class, EndpointAuthScheme.class), AwsEndpointAttribute.class);
-
- builder.beginControlFlow("if (authSchemes == null)")
- .addStatement("return request")
- .endControlFlow();
-
- // find the scheme to use
- builder.addStatement("$T chosenAuthScheme = $T.chooseAuthScheme(authSchemes)", EndpointAuthScheme.class,
- endpointRulesSpecUtils.rulesRuntimeClassName("AuthSchemeUtils"));
-
- // Create a signer provider
- builder.addStatement("$T signerProvider = signerProvider(chosenAuthScheme)", ParameterizedTypeName.get(Supplier.class,
- Signer.class));
-
- // Set signing attributes
- builder.addStatement("$T.setSigningParams(executionAttributes, chosenAuthScheme)",
- endpointRulesSpecUtils.rulesRuntimeClassName("AuthSchemeUtils"));
-
- // Override signer
- builder.addStatement("return $T.overrideSignerIfNotOverridden(request, executionAttributes, signerProvider)",
- SignerOverrideUtils.class);
-
-
- return builder.build();
- }
-
- private MethodSpec signerProviderMethod() {
- MethodSpec.Builder builder = MethodSpec.methodBuilder("signerProvider")
- .addModifiers(Modifier.PRIVATE)
- .addParameter(EndpointAuthScheme.class, "authScheme")
- .returns(ParameterizedTypeName.get(Supplier.class, Signer.class));
-
- builder.beginControlFlow("switch (authScheme.name())");
- builder.addCode("case $S:", SIGV4_NAME);
- if (endpointRulesSpecUtils.isS3() || endpointRulesSpecUtils.isS3Control()) {
- builder.addStatement("return $T::create", AwsS3V4Signer.class);
- } else {
- builder.addStatement("return $T::create", Aws4Signer.class);
- }
-
- builder.addCode("case $S:", SIGV4A_NAME);
- if (endpointRulesSpecUtils.isS3() || endpointRulesSpecUtils.isS3Control()) {
- builder.addStatement("return $T::getS3SigV4aSigner", SignerLoader.class);
- } else {
- builder.addStatement("return $T::getSigV4aSigner", SignerLoader.class);
- }
-
- builder.addCode("default:");
- builder.addStatement("break");
- builder.endControlFlow();
-
- builder.addStatement("throw $T.create($S + authScheme.name())",
- SdkClientException.class,
- "Don't know how to create signer for auth scheme: ");
-
- return builder.build();
- }
-}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointParametersClassSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointParametersClassSpec.java
index a330213aa873..eebe516b02d2 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointParametersClassSpec.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointParametersClassSpec.java
@@ -15,14 +15,9 @@
package software.amazon.awssdk.codegen.poet.rules;
-import com.fasterxml.jackson.core.TreeNode;
-import com.fasterxml.jackson.jr.stree.JrsBoolean;
-import com.fasterxml.jackson.jr.stree.JrsString;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
@@ -30,11 +25,9 @@
import javax.lang.model.element.Modifier;
import software.amazon.awssdk.annotations.SdkPublicApi;
import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
-import software.amazon.awssdk.codegen.model.rules.endpoints.BuiltInParameter;
import software.amazon.awssdk.codegen.model.rules.endpoints.ParameterModel;
import software.amazon.awssdk.codegen.poet.ClassSpec;
import software.amazon.awssdk.codegen.poet.PoetUtils;
-import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.utils.builder.CopyableBuilder;
import software.amazon.awssdk.utils.builder.ToCopyableBuilder;
@@ -61,8 +54,8 @@ public TypeSpec poetSpec() {
.addModifiers(Modifier.PUBLIC, Modifier.FINAL);
parameters().forEach((name, model) -> {
- b.addField(fieldSpec(name, model).toBuilder().addModifiers(Modifier.FINAL).build());
- b.addMethod(accessorMethod(name, model));
+ b.addField(endpointRulesSpecUtils.parameterClassField(name, model));
+ b.addMethod(endpointRulesSpecUtils.parameterClassAccessorMethod(name, model));
});
b.addMethod(toBuilderMethod());
@@ -81,7 +74,7 @@ private TypeSpec builderInterfaceSpec() {
.addModifiers(Modifier.PUBLIC);
parameters().forEach((name, model) -> {
- b.addMethod(setterMethodDeclaration(name, model));
+ b.addMethod(endpointRulesSpecUtils.parameterBuilderSetterMethodDeclaration(className(), name, model));
});
b.addMethod(MethodSpec.methodBuilder("build")
@@ -103,8 +96,8 @@ private TypeSpec builderImplSpec() {
b.addMethod(toBuilderConstructor().build());
parameters().forEach((name, model) -> {
- b.addField(fieldSpec(name, model).toBuilder().initializer(defaultValueCode(model)).build());
- b.addMethod(builderSetterMethod(name, model));
+ b.addField(endpointRulesSpecUtils.parameterBuilderFieldSpec(name, model));
+ b.addMethod(endpointRulesSpecUtils.parameterBuilderSetterMethod(className(), name, model));
});
b.addMethod(MethodSpec.methodBuilder("build")
@@ -131,51 +124,6 @@ private Map parameters() {
return intermediateModel.getEndpointRuleSetModel().getParameters();
}
- private ParameterSpec parameterSpec(String name, ParameterModel model) {
- return ParameterSpec.builder(endpointRulesSpecUtils.parameterType(model), variableName(name)).build();
- }
-
- private FieldSpec fieldSpec(String name, ParameterModel model) {
- return FieldSpec.builder(endpointRulesSpecUtils.parameterType(model), variableName(name))
- .addModifiers(Modifier.PRIVATE)
- .build();
- }
-
- private MethodSpec setterMethodDeclaration(String name, ParameterModel model) {
- MethodSpec.Builder b = paramMethodBuilder(name, model);
- b.addModifiers(Modifier.ABSTRACT);
- b.addParameter(parameterSpec(name, model));
- b.returns(builderInterfaceName());
- return b.build();
- }
-
- private MethodSpec accessorMethod(String name, ParameterModel model) {
- MethodSpec.Builder b = paramMethodBuilder(name, model);
- b.returns(endpointRulesSpecUtils.parameterType(model));
- b.addStatement("return $N", variableName(name));
- return b.build();
- }
-
- private MethodSpec builderSetterMethod(String name, ParameterModel model) {
- String memberName = variableName(name);
-
- MethodSpec.Builder b = paramMethodBuilder(name, model)
- .addAnnotation(Override.class)
- .addParameter(parameterSpec(name, model))
- .returns(builderInterfaceName())
- .addStatement("this.$1N = $1N", memberName);
-
- TreeNode defaultValue = model.getDefault();
- if (defaultValue != null) {
- b.beginControlFlow("if (this.$N == null)", memberName);
- b.addStatement("this.$N = $L", memberName, defaultValueCode(model));
- b.endControlFlow();
- }
-
- b.addStatement("return this");
- return b.build();
- }
-
private MethodSpec ctor() {
MethodSpec.Builder b = MethodSpec.constructorBuilder()
.addModifiers(Modifier.PRIVATE)
@@ -208,44 +156,6 @@ private String variableName(String name) {
return intermediateModel.getNamingStrategy().getVariableName(name);
}
- private CodeBlock defaultValueCode(ParameterModel parameterModel) {
- CodeBlock.Builder b = CodeBlock.builder();
-
- TreeNode defaultValue = parameterModel.getDefault();
-
- if (defaultValue == null) {
- return b.build();
- }
-
- switch (defaultValue.asToken()) {
- case VALUE_STRING:
- String stringValue = ((JrsString) defaultValue).getValue();
- if (parameterModel.getBuiltInEnum() == BuiltInParameter.AWS_REGION) {
- b.add("$T.of($S)", Region.class, stringValue);
- } else {
- b.add("$S", stringValue);
- }
- break;
- case VALUE_TRUE:
- case VALUE_FALSE:
- b.add("$L", ((JrsBoolean) defaultValue).booleanValue());
- break;
- default:
- throw new RuntimeException("Don't know how to set default value for parameter of type "
- + defaultValue.asToken());
- }
- return b.build();
- }
-
- private MethodSpec.Builder paramMethodBuilder(String name, ParameterModel model) {
- MethodSpec.Builder b = MethodSpec.methodBuilder(endpointRulesSpecUtils.paramMethodName(name));
- b.addModifiers(Modifier.PUBLIC);
- if (model.getDeprecated() != null) {
- b.addAnnotation(Deprecated.class);
- }
- return b;
- }
-
private MethodSpec.Builder toBuilderConstructor() {
MethodSpec.Builder constructorBuilder = MethodSpec.constructorBuilder();
constructorBuilder.addModifiers(Modifier.PRIVATE);
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointResolverInterceptorSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointResolverInterceptorSpec.java
index 9a8cdfdc127d..38fe5355b1d1 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointResolverInterceptorSpec.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointResolverInterceptorSpec.java
@@ -19,16 +19,30 @@
import com.fasterxml.jackson.jr.stree.JrsBoolean;
import com.fasterxml.jackson.jr.stree.JrsString;
import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterizedTypeName;
+import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
+import com.squareup.javapoet.TypeVariableName;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import java.util.Optional;
+import java.util.Set;
import java.util.concurrent.CompletionException;
+import java.util.function.Supplier;
import javax.lang.model.element.Modifier;
import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.auth.signer.Aws4Signer;
+import software.amazon.awssdk.auth.signer.AwsS3V4Signer;
+import software.amazon.awssdk.auth.signer.SignerLoader;
import software.amazon.awssdk.awscore.AwsExecutionAttribute;
+import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute;
+import software.amazon.awssdk.awscore.endpoints.authscheme.EndpointAuthScheme;
+import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4AuthScheme;
+import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4aAuthScheme;
+import software.amazon.awssdk.awscore.util.SignerOverrideUtils;
import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
import software.amazon.awssdk.codegen.model.intermediate.OperationModel;
import software.amazon.awssdk.codegen.model.rules.endpoints.ParameterModel;
@@ -40,14 +54,25 @@
import software.amazon.awssdk.codegen.poet.ClassSpec;
import software.amazon.awssdk.codegen.poet.PoetExtension;
import software.amazon.awssdk.codegen.poet.PoetUtils;
+import software.amazon.awssdk.codegen.poet.auth.scheme.AuthSchemeSpecUtils;
import software.amazon.awssdk.core.SdkRequest;
+import software.amazon.awssdk.core.SelectedAuthScheme;
import software.amazon.awssdk.core.exception.SdkClientException;
import software.amazon.awssdk.core.interceptor.Context;
import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
import software.amazon.awssdk.core.interceptor.SdkExecutionAttribute;
import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute;
+import software.amazon.awssdk.core.signer.Signer;
import software.amazon.awssdk.endpoints.Endpoint;
+import software.amazon.awssdk.http.SdkHttpRequest;
+import software.amazon.awssdk.http.auth.aws.scheme.AwsV4AuthScheme;
+import software.amazon.awssdk.http.auth.aws.scheme.AwsV4aAuthScheme;
+import software.amazon.awssdk.http.auth.aws.signer.AwsV4HttpSigner;
+import software.amazon.awssdk.http.auth.aws.signer.AwsV4aHttpSigner;
+import software.amazon.awssdk.http.auth.aws.signer.RegionSet;
+import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption;
+import software.amazon.awssdk.identity.spi.Identity;
import software.amazon.awssdk.utils.AttributeMap;
import software.amazon.awssdk.utils.HostnameValidator;
import software.amazon.awssdk.utils.StringUtils;
@@ -56,11 +81,21 @@ public class EndpointResolverInterceptorSpec implements ClassSpec {
private final IntermediateModel model;
private final EndpointRulesSpecUtils endpointRulesSpecUtils;
private final PoetExtension poetExtension;
+ private final boolean dependsOnHttpAuthAws;
+ private final boolean useSraAuth;
public EndpointResolverInterceptorSpec(IntermediateModel model) {
this.model = model;
this.endpointRulesSpecUtils = new EndpointRulesSpecUtils(model);
this.poetExtension = new PoetExtension(model);
+
+ // We need to know whether the service has a dependency on the http-auth-aws module. Because we can't check that
+ // directly, assume that if they're using AwsV4AuthScheme or AwsV4aAuthScheme that it's available.
+ Set> supportedAuthSchemes = new AuthSchemeSpecUtils(model).allServiceConcreteAuthSchemeClasses();
+ this.dependsOnHttpAuthAws = supportedAuthSchemes.contains(AwsV4AuthScheme.class) ||
+ supportedAuthSchemes.contains(AwsV4aAuthScheme.class);
+
+ this.useSraAuth = new AuthSchemeSpecUtils(model).useSraAuth();
}
@Override
@@ -71,6 +106,7 @@ public TypeSpec poetSpec() {
.addSuperinterface(ExecutionInterceptor.class);
b.addMethod(modifyRequestMethod());
+ b.addMethod(modifyHttpRequestMethod());
b.addMethod(ruleParams());
b.addMethod(setContextParams());
@@ -79,12 +115,18 @@ public TypeSpec poetSpec() {
b.addMethod(setStaticContextParamsMethod());
addStaticContextParamMethods(b);
+ b.addMethod(authSchemeWithEndpointSignerPropertiesMethod());
+
if (hasClientContextParams()) {
b.addMethod(setClientContextParamsMethod());
}
b.addMethod(hostPrefixMethod());
+ if (!useSraAuth) {
+ b.addMethod(signerProviderMethod());
+ }
+
return b.build();
}
@@ -104,28 +146,55 @@ private MethodSpec modifyRequestMethod() {
String providerVar = "provider";
+ b.addStatement("$T result = context.request()", SdkRequest.class);
// We skip resolution if the source of the endpoint is the endpoint discovery call
b.beginControlFlow("if ($1T.endpointIsDiscovered(executionAttributes))",
endpointRulesSpecUtils.rulesRuntimeClassName("AwsEndpointProviderUtils"));
- b.addStatement("return context.request()");
+ b.addStatement("return result");
b.endControlFlow();
b.addStatement("$1T $2N = ($1T) executionAttributes.getAttribute($3T.ENDPOINT_PROVIDER)",
endpointRulesSpecUtils.providerInterfaceName(), providerVar, SdkInternalExecutionAttribute.class);
b.beginControlFlow("try");
- b.addStatement("$T result = $N.resolveEndpoint(ruleParams(context, executionAttributes)).join()", Endpoint.class,
- providerVar);
+ b.addStatement("$T endpoint = $N.resolveEndpoint(ruleParams(result, executionAttributes)).join()",
+ Endpoint.class, providerVar);
b.beginControlFlow("if (!$T.disableHostPrefixInjection(executionAttributes))",
endpointRulesSpecUtils.rulesRuntimeClassName("AwsEndpointProviderUtils"));
- b.addStatement("$T hostPrefix = hostPrefix(executionAttributes.getAttribute($T.OPERATION_NAME), context.request())",
+ b.addStatement("$T hostPrefix = hostPrefix(executionAttributes.getAttribute($T.OPERATION_NAME), result)",
ParameterizedTypeName.get(Optional.class, String.class), SdkExecutionAttribute.class);
b.beginControlFlow("if (hostPrefix.isPresent())");
- b.addStatement("result = $T.addHostPrefix(result, hostPrefix.get())",
+ b.addStatement("endpoint = $T.addHostPrefix(endpoint, hostPrefix.get())",
endpointRulesSpecUtils.rulesRuntimeClassName("AwsEndpointProviderUtils"));
b.endControlFlow();
b.endControlFlow();
- b.addStatement("executionAttributes.putAttribute(SdkInternalExecutionAttribute.RESOLVED_ENDPOINT, result)");
- b.addStatement("return context.request()");
+
+
+ // If the endpoint resolver returns auth settings, use them as signer properties.
+ // This effectively works to set the preSRA Signer ExecutionAttributes, so it is not conditional on useSraAuth.
+ b.addStatement("$T<$T> endpointAuthSchemes = endpoint.attribute($T.AUTH_SCHEMES)",
+ List.class, EndpointAuthScheme.class, AwsEndpointAttribute.class);
+ b.addStatement("$T> selectedAuthScheme = executionAttributes.getAttribute($T.SELECTED_AUTH_SCHEME)",
+ SelectedAuthScheme.class, SdkInternalExecutionAttribute.class);
+ b.beginControlFlow("if (endpointAuthSchemes != null && selectedAuthScheme != null)");
+ b.addStatement("selectedAuthScheme = authSchemeWithEndpointSignerProperties(endpointAuthSchemes, selectedAuthScheme)");
+
+ b.addStatement("executionAttributes.putAttribute($T.SELECTED_AUTH_SCHEME, selectedAuthScheme)",
+ SdkInternalExecutionAttribute.class);
+ b.endControlFlow();
+
+ // For pre SRA client, use Signer as determined by endpoint resolved auth scheme
+ if (!useSraAuth) {
+ b.beginControlFlow("if (endpointAuthSchemes != null)");
+ b.addStatement("$T chosenAuthScheme = $T.chooseAuthScheme(endpointAuthSchemes)", EndpointAuthScheme.class,
+ endpointRulesSpecUtils.rulesRuntimeClassName("AuthSchemeUtils"));
+ b.addStatement("$T<$T> signerProvider = signerProvider(chosenAuthScheme)", Supplier.class, Signer.class);
+ b.addStatement("result = $T.overrideSignerIfNotOverridden(result, executionAttributes, signerProvider)",
+ SignerOverrideUtils.class);
+ b.endControlFlow();
+ }
+
+ b.addStatement("executionAttributes.putAttribute(SdkInternalExecutionAttribute.RESOLVED_ENDPOINT, endpoint)");
+ b.addStatement("return result");
b.endControlFlow();
b.beginControlFlow("catch ($T e)", CompletionException.class);
b.addStatement("$T cause = e.getCause()", Throwable.class);
@@ -139,11 +208,34 @@ private MethodSpec modifyRequestMethod() {
return b.build();
}
+ private MethodSpec modifyHttpRequestMethod() {
+ MethodSpec.Builder b = MethodSpec.methodBuilder("modifyHttpRequest")
+ .addModifiers(Modifier.PUBLIC)
+ .addAnnotation(Override.class)
+ .returns(SdkHttpRequest.class)
+ .addParameter(Context.ModifyHttpRequest.class, "context")
+ .addParameter(ExecutionAttributes.class, "executionAttributes");
+
+ b.addStatement("$T resolvedEndpoint = executionAttributes.getAttribute($T.RESOLVED_ENDPOINT)",
+ Endpoint.class, SdkInternalExecutionAttribute.class);
+ b.beginControlFlow("if (resolvedEndpoint.headers().isEmpty())");
+ b.addStatement("return context.httpRequest()");
+ b.endControlFlow();
+
+ b.addStatement("$T httpRequestBuilder = context.httpRequest().toBuilder()", SdkHttpRequest.Builder.class);
+ b.addCode("resolvedEndpoint.headers().forEach((name, values) -> {");
+ b.addStatement("values.forEach(v -> httpRequestBuilder.appendHeader(name, v))");
+ b.addCode("});");
+ b.addStatement("return httpRequestBuilder.build()");
+
+ return b.build();
+ }
+
private MethodSpec ruleParams() {
MethodSpec.Builder b = MethodSpec.methodBuilder("ruleParams")
- .addModifiers(Modifier.PRIVATE, Modifier.STATIC)
+ .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
.returns(endpointRulesSpecUtils.parametersClassName())
- .addParameter(Context.ModifyRequest.class, "context")
+ .addParameter(SdkRequest.class, "request")
.addParameter(ExecutionAttributes.class, "executionAttributes");
b.addStatement("$T builder = $T.builder()", paramsBuilderClass(), endpointRulesSpecUtils.parametersClassName());
@@ -194,7 +286,7 @@ private MethodSpec ruleParams() {
if (hasClientContextParams()) {
b.addStatement("setClientContextParams(builder, executionAttributes)");
}
- b.addStatement("setContextParams(builder, executionAttributes.getAttribute($T.OPERATION_NAME), context.request())",
+ b.addStatement("setContextParams(builder, executionAttributes.getAttribute($T.OPERATION_NAME), request)",
AwsExecutionAttribute.class);
b.addStatement("setStaticContextParams(builder, executionAttributes.getAttribute($T.OPERATION_NAME))",
AwsExecutionAttribute.class);
@@ -452,4 +544,132 @@ private String getHostPrefix(OperationModel opModel) {
return endpointTrait.getHostPrefix();
}
+
+ private MethodSpec authSchemeWithEndpointSignerPropertiesMethod() {
+ TypeVariableName tExtendsIdentity = TypeVariableName.get("T", Identity.class);
+ TypeName selectedAuthSchemeOfT = ParameterizedTypeName.get(ClassName.get(SelectedAuthScheme.class),
+ TypeVariableName.get("T"));
+ TypeName listOfEndpointAuthScheme = ParameterizedTypeName.get(List.class, EndpointAuthScheme.class);
+
+ MethodSpec.Builder method =
+ MethodSpec.methodBuilder("authSchemeWithEndpointSignerProperties")
+ .addModifiers(Modifier.PRIVATE)
+ .addTypeVariable(tExtendsIdentity)
+ .returns(selectedAuthSchemeOfT)
+ .addParameter(listOfEndpointAuthScheme, "endpointAuthSchemes")
+ .addParameter(selectedAuthSchemeOfT, "selectedAuthScheme");
+
+ method.beginControlFlow("for ($T endpointAuthScheme : endpointAuthSchemes)", EndpointAuthScheme.class);
+
+ if (useSraAuth) {
+ // Don't include signer properties for auth options that don't match our selected auth scheme
+ method.beginControlFlow("if (!endpointAuthScheme.schemeId()"
+ + ".equals(selectedAuthScheme.authSchemeOption().schemeId()))");
+ method.addStatement("continue");
+ method.endControlFlow();
+ }
+
+ method.addStatement("$T option = selectedAuthScheme.authSchemeOption().toBuilder()", AuthSchemeOption.Builder.class);
+
+ if (dependsOnHttpAuthAws) {
+ method.addCode(copyV4EndpointSignerPropertiesToAuth());
+ method.addCode(copyV4aEndpointSignerPropertiesToAuth());
+ }
+
+ method.addStatement("throw new $T(\"Endpoint auth scheme '\" + endpointAuthScheme.name() + \"' cannot be mapped to the "
+ + "SDK auth scheme. Was it declared in the service's model?\")",
+ IllegalArgumentException.class);
+
+ method.endControlFlow();
+
+ method.addStatement("return selectedAuthScheme");
+
+ return method.build();
+ }
+
+ private static CodeBlock copyV4EndpointSignerPropertiesToAuth() {
+ CodeBlock.Builder code = CodeBlock.builder();
+ code.beginControlFlow("if (endpointAuthScheme instanceof $T)", SigV4AuthScheme.class);
+ code.addStatement("$1T v4AuthScheme = ($1T) endpointAuthScheme", SigV4AuthScheme.class);
+
+ code.beginControlFlow("if (v4AuthScheme.isDisableDoubleEncodingSet())");
+ code.addStatement("option.putSignerProperty($T.DOUBLE_URL_ENCODE, !v4AuthScheme.disableDoubleEncoding())",
+ AwsV4HttpSigner.class);
+ code.endControlFlow();
+
+ code.beginControlFlow("if (v4AuthScheme.signingRegion() != null)");
+ code.addStatement("option.putSignerProperty($T.REGION_NAME, v4AuthScheme.signingRegion())",
+ AwsV4HttpSigner.class);
+ code.endControlFlow();
+
+ code.beginControlFlow("if (v4AuthScheme.signingName() != null)");
+ code.addStatement("option.putSignerProperty($T.SERVICE_SIGNING_NAME, v4AuthScheme.signingName())",
+ AwsV4HttpSigner.class);
+ code.endControlFlow();
+
+ code.addStatement("return new $T<>(selectedAuthScheme.identity(), selectedAuthScheme.signer(), option.build())",
+ SelectedAuthScheme.class);
+ code.endControlFlow();
+ return code.build();
+ }
+
+ private static CodeBlock copyV4aEndpointSignerPropertiesToAuth() {
+ CodeBlock.Builder code = CodeBlock.builder();
+
+ code.beginControlFlow("if (endpointAuthScheme instanceof $T)", SigV4aAuthScheme.class);
+ code.addStatement("$1T v4aAuthScheme = ($1T) endpointAuthScheme", SigV4aAuthScheme.class);
+
+ code.beginControlFlow("if (v4aAuthScheme.isDisableDoubleEncodingSet())");
+ code.addStatement("option.putSignerProperty($T.DOUBLE_URL_ENCODE, !v4aAuthScheme.disableDoubleEncoding())",
+ AwsV4aHttpSigner.class);
+ code.endControlFlow();
+
+ code.beginControlFlow("if (v4aAuthScheme.signingRegionSet() != null)");
+ code.addStatement("$1T regionSet = $1T.create(v4aAuthScheme.signingRegionSet())", RegionSet.class);
+
+ code.addStatement("option.putSignerProperty($T.REGION_SET, regionSet)", AwsV4aHttpSigner.class);
+ code.endControlFlow();
+
+ code.beginControlFlow("if (v4aAuthScheme.signingName() != null)");
+ code.addStatement("option.putSignerProperty($T.SERVICE_SIGNING_NAME, v4aAuthScheme.signingName())",
+ AwsV4aHttpSigner.class);
+ code.endControlFlow();
+
+ code.addStatement("return new $T<>(selectedAuthScheme.identity(), selectedAuthScheme.signer(), option.build())",
+ SelectedAuthScheme.class);
+ code.endControlFlow();
+ return code.build();
+ }
+
+ private MethodSpec signerProviderMethod() {
+ MethodSpec.Builder builder = MethodSpec.methodBuilder("signerProvider")
+ .addModifiers(Modifier.PRIVATE)
+ .addParameter(EndpointAuthScheme.class, "authScheme")
+ .returns(ParameterizedTypeName.get(Supplier.class, Signer.class));
+
+ builder.beginControlFlow("switch (authScheme.name())");
+ builder.addCode("case $S:", "sigv4");
+ if (endpointRulesSpecUtils.isS3() || endpointRulesSpecUtils.isS3Control()) {
+ builder.addStatement("return $T::create", AwsS3V4Signer.class);
+ } else {
+ builder.addStatement("return $T::create", Aws4Signer.class);
+ }
+
+ builder.addCode("case $S:", "sigv4a");
+ if (endpointRulesSpecUtils.isS3() || endpointRulesSpecUtils.isS3Control()) {
+ builder.addStatement("return $T::getS3SigV4aSigner", SignerLoader.class);
+ } else {
+ builder.addStatement("return $T::getSigV4aSigner", SignerLoader.class);
+ }
+
+ builder.addCode("default:");
+ builder.addStatement("break");
+ builder.endControlFlow();
+
+ builder.addStatement("throw $T.create($S + authScheme.name())",
+ SdkClientException.class,
+ "Don't know how to create signer for auth scheme: ");
+
+ return builder.build();
+ }
}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointRulesSpecUtils.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointRulesSpecUtils.java
index f0cd296141b2..ef41c826bf3a 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointRulesSpecUtils.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointRulesSpecUtils.java
@@ -20,6 +20,9 @@
import com.fasterxml.jackson.jr.stree.JrsString;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.FieldSpec;
+import com.squareup.javapoet.MethodSpec;
+import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;
import java.io.IOException;
@@ -32,6 +35,7 @@
import java.util.jar.JarFile;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
+import javax.lang.model.element.Modifier;
import software.amazon.awssdk.codegen.internal.Utils;
import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
import software.amazon.awssdk.codegen.model.intermediate.Metadata;
@@ -78,12 +82,6 @@ public ClassName resolverInterceptorName() {
md.getServiceName() + "ResolveEndpointInterceptor");
}
- public ClassName authSchemesInterceptorName() {
- Metadata md = intermediateModel.getMetadata();
- return ClassName.get(md.getFullInternalEndpointRulesPackageName(),
- md.getServiceName() + "EndpointAuthSchemeInterceptor");
- }
-
public ClassName requestModifierInterceptorName() {
Metadata md = intermediateModel.getMetadata();
return ClassName.get(md.getFullInternalEndpointRulesPackageName(),
@@ -203,8 +201,197 @@ public List rulesEngineResourceFiles() {
}
}
+ public Map parameters() {
+ return intermediateModel.getEndpointRuleSetModel().getParameters();
+ }
+
public boolean isDeclaredParam(String paramName) {
Map parameters = intermediateModel.getEndpointRuleSetModel().getParameters();
return parameters.containsKey(paramName);
}
+
+ /**
+ * Creates a data-class level field for the given parameter. For instance
+ *
+ *
+ * private final Region region;
+ *
+ */
+ public FieldSpec parameterClassField(String name, ParameterModel model) {
+ return parameterFieldSpecBuilder(name, model)
+ .addModifiers(Modifier.PRIVATE)
+ .addModifiers(Modifier.FINAL)
+ .build();
+ }
+
+ /**
+ * Creates a data-class method to access the given parameter. For instance
+ *
+ *
+ * public Region region() {…};
+ *
+ */
+ public MethodSpec parameterClassAccessorMethod(String name, ParameterModel model) {
+ MethodSpec.Builder b = parameterMethodBuilder(name, model);
+ b.returns(parameterType(model));
+ b.addStatement("return $N", variableName(name));
+ return b.build();
+ }
+
+
+ /**
+ * Creates a data-interface method to access the given parameter. For instance
+ *
+ *
+ * Region region();
+ *
+ */
+ public MethodSpec parameterInterfaceAccessorMethod(String name, ParameterModel model) {
+ MethodSpec.Builder b = parameterMethodBuilder(name, model);
+ b.returns(parameterType(model));
+ b.addModifiers(Modifier.ABSTRACT);
+ return b.build();
+ }
+
+ /**
+ * Creates a builder-class level field for the given parameter initialized to its default value when present. For instance
+ *
+ *
+ * private Boolean useGlobalEndpoint = false;
+ *
+ */
+ public FieldSpec parameterBuilderFieldSpec(String name, ParameterModel model) {
+ return parameterFieldSpecBuilder(name, model)
+ .initializer(parameterDefaultValueCode(model))
+ .build();
+ }
+
+ /**
+ * Creates a builder-interface method to set the given parameter. For instance
+ *
+ *
+ * Builder region(Region region);
+ *
+ *
+ */
+ public MethodSpec parameterBuilderSetterMethodDeclaration(ClassName containingClass, String name, ParameterModel model) {
+ MethodSpec.Builder b = parameterMethodBuilder(name, model);
+ b.addModifiers(Modifier.ABSTRACT);
+ b.addParameter(parameterSpec(name, model));
+ b.returns(containingClass.nestedClass("Builder"));
+ return b.build();
+ }
+
+ /**
+ * Creates a builder-class method to set the given parameter. For instance
+ *
+ *
+ * public Builder region(Region region) {…};
+ *
+ */
+ public MethodSpec parameterBuilderSetterMethod(ClassName containingClass, String name, ParameterModel model) {
+ String memberName = variableName(name);
+
+ MethodSpec.Builder b = parameterMethodBuilder(name, model)
+ .addAnnotation(Override.class)
+ .addParameter(parameterSpec(name, model))
+ .returns(containingClass.nestedClass("Builder"))
+ .addStatement("this.$1N = $1N", memberName);
+
+ TreeNode defaultValue = model.getDefault();
+ if (defaultValue != null) {
+ b.beginControlFlow("if (this.$N == null)", memberName);
+ b.addStatement("this.$N = $L", memberName, parameterDefaultValueCode(model));
+ b.endControlFlow();
+ }
+
+ b.addStatement("return this");
+ return b.build();
+ }
+
+ /**
+ * Used internally to create a field for the given parameter. Returns the builder that can be further tailor to be used for
+ * data-classes or for builder-classes.
+ */
+ private FieldSpec.Builder parameterFieldSpecBuilder(String name, ParameterModel model) {
+ return FieldSpec.builder(parameterType(model), variableName(name))
+ .addModifiers(Modifier.PRIVATE);
+ }
+
+ /**
+ * Used internally to create the spec for a parameter to be used in a method for the given param model. For instance, for
+ * {@code ParameterModel} for {@code Region} it creates this parameter for the builder setter.
+ *
+ *
+ * public Builder region(
+ * Region region // <<--- This
+ * ) {…};
+ *
+ */
+ private ParameterSpec parameterSpec(String name, ParameterModel model) {
+ return ParameterSpec.builder(parameterType(model), variableName(name)).build();
+ }
+
+ /**
+ * Used internally to create a accessor method for the given parameter model. Returns the builder that can be further
+ * tailor to be used for data-classes/interfaces and builder-classes/interfaces.
+ */
+ private MethodSpec.Builder parameterMethodBuilder(String name, ParameterModel model) {
+ MethodSpec.Builder b = MethodSpec.methodBuilder(paramMethodName(name));
+ b.addModifiers(Modifier.PUBLIC);
+ if (model.getDeprecated() != null) {
+ b.addAnnotation(Deprecated.class);
+ }
+ return b;
+ }
+
+ /**
+ * Used internally to create the code to initialize the default value modeled for the given parameter. For instance, if the
+ * modeled default for region is "us-east-1", it will create
+ *
+ *
+ * Region.of("us-east-1")
+ *
+ *
+ * and if the modeled default value for a boolean parameter useGlobalEndpoint is "false", it will create
+ *
+ *
+ * false
+ *
+ */
+ private CodeBlock parameterDefaultValueCode(ParameterModel parameterModel) {
+ CodeBlock.Builder b = CodeBlock.builder();
+
+ TreeNode defaultValue = parameterModel.getDefault();
+
+ if (defaultValue == null) {
+ return b.build();
+ }
+
+ switch (defaultValue.asToken()) {
+ case VALUE_STRING:
+ String stringValue = ((JrsString) defaultValue).getValue();
+ if (parameterModel.getBuiltInEnum() == BuiltInParameter.AWS_REGION) {
+ b.add("$T.of($S)", Region.class, stringValue);
+ } else {
+ b.add("$S", stringValue);
+ }
+ break;
+ case VALUE_TRUE:
+ case VALUE_FALSE:
+ b.add("$L", ((JrsBoolean) defaultValue).booleanValue());
+ break;
+ default:
+ throw new RuntimeException("Don't know how to set default value for parameter of type "
+ + defaultValue.asToken());
+ }
+ return b.build();
+ }
+
+ /**
+ * Returns the name as a variable name using the intermediate model naming strategy.
+ */
+ public String variableName(String name) {
+ return intermediateModel.getNamingStrategy().getVariableName(name);
+ }
}
diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/poet/model/SdkClientConfigurationUtil.resource.java b/codegen/src/main/resources/software/amazon/awssdk/codegen/poet/model/SdkClientConfigurationUtil.resource.java
new file mode 100644
index 000000000000..f5602795ad45
--- /dev/null
+++ b/codegen/src/main/resources/software/amazon/awssdk/codegen/poet/model/SdkClientConfigurationUtil.resource.java
@@ -0,0 +1,103 @@
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.core.client.config.ClientOption;
+import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration;
+import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption;
+import software.amazon.awssdk.core.client.config.SdkClientConfiguration;
+import software.amazon.awssdk.core.client.config.SdkClientOption;
+import software.amazon.awssdk.core.internal.SdkInternalTestAdvancedClientOption;
+import software.amazon.awssdk.core.signer.Signer;
+import software.amazon.awssdk.profiles.ProfileFile;
+import software.amazon.awssdk.profiles.ProfileFileSupplier;
+
+@SdkInternalApi
+public final class SdkClientConfigurationUtil {
+ private SdkClientConfigurationUtil() {
+ }
+
+ /**
+ * Copies the {@link ClientOverrideConfiguration} values to the configuration builder.
+ */
+ public static SdkClientConfiguration.Builder copyOverridesToConfiguration(ClientOverrideConfiguration overrides,
+ SdkClientConfiguration.Builder builder) {
+
+ // misc
+ setClientOption(builder, SdkClientOption.ADDITIONAL_HTTP_HEADERS, overrides.headers());
+ setClientOption(builder, SdkClientOption.RETRY_POLICY, overrides.retryPolicy());
+ setClientOption(builder, SdkClientOption.API_CALL_TIMEOUT, overrides.apiCallTimeout());
+ setClientOption(builder, SdkClientOption.API_CALL_ATTEMPT_TIMEOUT, overrides.apiCallAttemptTimeout());
+ setClientOption(builder, SdkClientOption.SCHEDULED_EXECUTOR_SERVICE, overrides.scheduledExecutorService());
+ setClientListOption(builder, SdkClientOption.EXECUTION_INTERCEPTORS, overrides.executionInterceptors());
+ setClientOption(builder, SdkClientOption.EXECUTION_ATTRIBUTES, overrides.executionAttributes());
+
+ // advanced option
+ Signer signer = overrides.advancedOption(SdkAdvancedClientOption.SIGNER).orElse(null);
+ if (signer != null) {
+ builder.option(SdkAdvancedClientOption.SIGNER, signer);
+ builder.option(SdkClientOption.SIGNER_OVERRIDDEN, true);
+ }
+ setClientOption(builder, SdkAdvancedClientOption.USER_AGENT_SUFFIX,
+ overrides.advancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX));
+ setClientOption(builder, SdkAdvancedClientOption.USER_AGENT_PREFIX,
+ overrides.advancedOption(SdkAdvancedClientOption.USER_AGENT_PREFIX));
+ setClientOption(builder, SdkAdvancedClientOption.DISABLE_HOST_PREFIX_INJECTION,
+ overrides.advancedOption(SdkAdvancedClientOption.DISABLE_HOST_PREFIX_INJECTION));
+ overrides.advancedOption(SdkInternalTestAdvancedClientOption.ENDPOINT_OVERRIDDEN_OVERRIDE).ifPresent(value -> {
+ builder.option(SdkClientOption.ENDPOINT_OVERRIDDEN, value);
+ });
+
+ // profile
+ ProfileFile profileFile = overrides.defaultProfileFile().orElse(null);
+ if (profileFile != null) {
+ builder.option(SdkClientOption.PROFILE_FILE_SUPPLIER, ProfileFileSupplier.fixedProfileFile(profileFile));
+ }
+ setClientOption(builder, SdkClientOption.PROFILE_NAME, overrides.defaultProfileName());
+
+ // misc
+ setClientListOption(builder, SdkClientOption.METRIC_PUBLISHERS, overrides.metricPublishers());
+ setClientOption(builder, SdkAdvancedClientOption.TOKEN_SIGNER,
+ overrides.advancedOption(SdkAdvancedClientOption.TOKEN_SIGNER));
+ setClientOption(builder, SdkClientOption.COMPRESSION_CONFIGURATION, overrides.compressionConfiguration());
+
+ return builder;
+ }
+
+ static void setClientOption(SdkClientConfiguration.Builder builder, ClientOption option, T newValue) {
+ if (newValue != null) {
+ T oldValue = builder.option(option);
+ if (oldValue == null || !oldValue.equals(newValue)) {
+ builder.option(option, newValue);
+ }
+ }
+ }
+
+ static void setClientOption(SdkClientConfiguration.Builder builder, ClientOption option, Optional newValueOpt) {
+ setClientOption(builder, option, newValueOpt.orElse(null));
+ }
+
+ static void setClientListOption(SdkClientConfiguration.Builder builder, ClientOption> option, List newValue) {
+ if (newValue == null || newValue.isEmpty()) {
+ return;
+ }
+ List oldValue = builder.option(option);
+ if (oldValue == null || oldValue.isEmpty()) {
+ builder.option(option, newValue);
+ return;
+ }
+ // Make sure that we don't override derived values or duplicate existing ones.
+ List result = new ArrayList<>(oldValue);
+ Set dedup = new HashSet<>();
+ dedup.addAll(oldValue);
+ for (T value : newValue) {
+ if (!dedup.contains(value)) {
+ result.add(value);
+ }
+ }
+ builder.option(option, result);
+ }
+}
diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/AuthSchemeUtils.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/AuthSchemeUtils.java.resource
index ce36d0571828..e90be4fdde7c 100644
--- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/AuthSchemeUtils.java.resource
+++ b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/AuthSchemeUtils.java.resource
@@ -4,16 +4,19 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import software.amazon.awssdk.annotations.SdkProtectedApi;
-import software.amazon.awssdk.auth.signer.AwsSignerExecutionAttribute;
import software.amazon.awssdk.awscore.endpoints.authscheme.EndpointAuthScheme;
import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4AuthScheme;
import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4aAuthScheme;
+import software.amazon.awssdk.core.SelectedAuthScheme;
import software.amazon.awssdk.core.exception.SdkClientException;
import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
-import software.amazon.awssdk.regions.Region;
-import software.amazon.awssdk.regions.RegionScope;
+import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute;
+import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption;
+import software.amazon.awssdk.identity.spi.Identity;
import software.amazon.awssdk.utils.Logger;
+// TODO(sra-identity-auth): seems like this can be SdkInternalApi, similar to other .resource files in this folder,
+// since they are generated in each service module
@SdkProtectedApi
public final class AuthSchemeUtils {
private static final Logger LOG = Logger.loggerFor(AuthSchemeUtils.class);
@@ -54,102 +57,71 @@ public final class AuthSchemeUtils {
String authSchemeName = scheme.get(Identifier.of("name")).expectString();
switch (authSchemeName) {
- case SIGV4A_NAME: {
- SigV4aAuthScheme.Builder schemeBuilder = SigV4aAuthScheme.builder();
+ case SIGV4A_NAME: {
+ SigV4aAuthScheme.Builder schemeBuilder = SigV4aAuthScheme.builder();
- Value signingName = scheme.get(Identifier.of("signingName"));
- if (signingName != null) {
- schemeBuilder.signingName(signingName.expectString());
- }
-
- Value signingRegionSet = scheme.get(Identifier.of("signingRegionSet"));
- if (signingRegionSet != null) {
- Value.Array signingRegionSetArray = signingRegionSet.expectArray();
- for (int j = 0; j < signingRegionSetArray.size(); ++j) {
- schemeBuilder.addSigningRegion(signingRegionSetArray.get(j).expectString());
- }
- }
+ Value signingName = scheme.get(Identifier.of("signingName"));
+ if (signingName != null) {
+ schemeBuilder.signingName(signingName.expectString());
+ }
- Value disableDoubleEncoding = scheme.get(Identifier.of("disableDoubleEncoding"));
- if (disableDoubleEncoding != null) {
- schemeBuilder.disableDoubleEncoding(disableDoubleEncoding.expectBool());
+ Value signingRegionSet = scheme.get(Identifier.of("signingRegionSet"));
+ if (signingRegionSet != null) {
+ Value.Array signingRegionSetArray = signingRegionSet.expectArray();
+ for (int j = 0; j < signingRegionSetArray.size(); ++j) {
+ schemeBuilder.addSigningRegion(signingRegionSetArray.get(j).expectString());
}
+ }
- authSchemes.add(schemeBuilder.build());
+ Value disableDoubleEncoding = scheme.get(Identifier.of("disableDoubleEncoding"));
+ if (disableDoubleEncoding != null) {
+ schemeBuilder.disableDoubleEncoding(disableDoubleEncoding.expectBool());
}
- break;
- case SIGV4_NAME: {
- SigV4AuthScheme.Builder schemeBuilder = SigV4AuthScheme.builder();
- Value signingName = scheme.get(Identifier.of("signingName"));
- if (signingName != null) {
- schemeBuilder.signingName(signingName.expectString());
- }
+ authSchemes.add(schemeBuilder.build());
+ }
+ break;
+ case SIGV4_NAME: {
+ SigV4AuthScheme.Builder schemeBuilder = SigV4AuthScheme.builder();
- Value signingRegion = scheme.get(Identifier.of("signingRegion"));
- if (signingRegion != null) {
- schemeBuilder.signingRegion(signingRegion.expectString());
- }
+ Value signingName = scheme.get(Identifier.of("signingName"));
+ if (signingName != null) {
+ schemeBuilder.signingName(signingName.expectString());
+ }
- Value disableDoubleEncoding = scheme.get(Identifier.of("disableDoubleEncoding"));
- if (disableDoubleEncoding != null) {
- schemeBuilder.disableDoubleEncoding(disableDoubleEncoding.expectBool());
- }
+ Value signingRegion = scheme.get(Identifier.of("signingRegion"));
+ if (signingRegion != null) {
+ schemeBuilder.signingRegion(signingRegion.expectString());
+ }
- authSchemes.add(schemeBuilder.build());
+ Value disableDoubleEncoding = scheme.get(Identifier.of("disableDoubleEncoding"));
+ if (disableDoubleEncoding != null) {
+ schemeBuilder.disableDoubleEncoding(disableDoubleEncoding.expectBool());
}
+
+ authSchemes.add(schemeBuilder.build());
+ }
+ break;
+ default:
+ LOG.debug(() -> "Ignoring unknown auth scheme: " + authSchemeName);
break;
- default:
- LOG.debug(() -> "Ignoring unknown auth scheme: " + authSchemeName);
- break;
}
}
return authSchemes;
}
- public static void setSigningParams(ExecutionAttributes executionAttributes, EndpointAuthScheme authScheme) {
- if (authScheme instanceof SigV4AuthScheme) {
- setSigV4SigningParams(executionAttributes, (SigV4AuthScheme) authScheme);
- } else if (authScheme instanceof SigV4aAuthScheme) {
- setSigV4aAuthSigningParams(executionAttributes, (SigV4aAuthScheme) authScheme);
- } else {
- throw SdkClientException.create("Don't know how to set signing params for auth scheme: " + authScheme.name());
+ public static void putSelectedAuthScheme(ExecutionAttributes attributes,
+ SelectedAuthScheme selectedAuthScheme) {
+ SelectedAuthScheme> existingAuthScheme = attributes.getAttribute(SdkInternalExecutionAttribute.SELECTED_AUTH_SCHEME);
+ if (existingAuthScheme != null) {
+ AuthSchemeOption.Builder selectedOption = selectedAuthScheme.authSchemeOption().toBuilder();
+ existingAuthScheme.authSchemeOption().forEachIdentityProperty(selectedOption::putIdentityPropertyIfAbsent);
+ existingAuthScheme.authSchemeOption().forEachSignerProperty(selectedOption::putSignerPropertyIfAbsent);
+ selectedAuthScheme = new SelectedAuthScheme<>(selectedAuthScheme.identity(),
+ selectedAuthScheme.signer(),
+ selectedOption.build());
}
- }
-
- private static void setSigV4SigningParams(ExecutionAttributes executionAttributes, SigV4AuthScheme sigV4AuthScheme) {
- executionAttributes.putAttribute(AwsSignerExecutionAttribute.SIGNER_DOUBLE_URL_ENCODE,
- !sigV4AuthScheme.disableDoubleEncoding());
-
- if (sigV4AuthScheme.signingName() != null) {
- executionAttributes.putAttribute(AwsSignerExecutionAttribute.SERVICE_SIGNING_NAME, sigV4AuthScheme.signingName());
- }
-
- if (sigV4AuthScheme.signingRegion() != null) {
- executionAttributes.putAttribute(AwsSignerExecutionAttribute.SIGNING_REGION,
- Region.of(sigV4AuthScheme.signingRegion()));
- }
- }
-
- private static void setSigV4aAuthSigningParams(ExecutionAttributes executionAttributes, SigV4aAuthScheme sigV4aAuthScheme) {
- executionAttributes.putAttribute(AwsSignerExecutionAttribute.SIGNER_DOUBLE_URL_ENCODE,
- !sigV4aAuthScheme.disableDoubleEncoding());
- if (sigV4aAuthScheme.signingName() != null) {
- executionAttributes.putAttribute(AwsSignerExecutionAttribute.SERVICE_SIGNING_NAME, sigV4aAuthScheme.signingName());
- }
-
- if (sigV4aAuthScheme.signingRegionSet() != null) {
- if (sigV4aAuthScheme.signingRegionSet().size() > 1) {
- throw SdkClientException.create("Don't know how to set scope of > 1 region");
- }
-
- if (sigV4aAuthScheme.signingRegionSet().isEmpty()) {
- throw SdkClientException.create("Signing region set is empty");
- }
-
- String scope = sigV4aAuthScheme.signingRegionSet().get(0);
- executionAttributes.putAttribute(AwsSignerExecutionAttribute.SIGNING_REGION_SCOPE, RegionScope.create(scope));
- }
+ attributes.putAttribute(SdkInternalExecutionAttribute.SELECTED_AUTH_SCHEME, selectedAuthScheme);
}
}
diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/AwsEndpointProviderUtils.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/AwsEndpointProviderUtils.java.resource
index a9a5c05de4d7..83a9d65cb3eb 100644
--- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/AwsEndpointProviderUtils.java.resource
+++ b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/AwsEndpointProviderUtils.java.resource
@@ -1,13 +1,10 @@
import static software.amazon.awssdk.utils.FunctionalUtils.invokeSafely;
import java.net.URI;
-import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import software.amazon.awssdk.annotations.SdkInternalApi;
import software.amazon.awssdk.awscore.AwsExecutionAttribute;
-import software.amazon.awssdk.awscore.AwsRequest;
-import software.amazon.awssdk.awscore.AwsRequestOverrideConfiguration;
import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute;
import software.amazon.awssdk.core.exception.SdkClientException;
import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
@@ -96,11 +93,9 @@ public final class AwsEndpointProviderUtils {
URI originalUrl = endpoint.url();
String newHost = prefix + endpoint.url().getHost();
URI newUrl = invokeSafely(() -> new URI(originalUrl.getScheme(), null, newHost, originalUrl.getPort(),
- originalUrl.getPath(), originalUrl.getQuery(), originalUrl.getFragment()));
+ originalUrl.getPath(), originalUrl.getQuery(), originalUrl.getFragment()));
- return endpoint.toBuilder()
- .url(newUrl)
- .build();
+ return endpoint.toBuilder().url(newUrl).build();
}
public static Endpoint valueAsEndpointOrThrow(Value value) {
@@ -167,14 +162,15 @@ public final class AwsEndpointProviderUtils {
}
return request.toBuilder().protocol(resolvedUri.getScheme()).host(resolvedUri.getHost()).port(resolvedUri.getPort())
- .encodedPath(finalPath).build();
+ .encodedPath(finalPath).build();
}
/**
- * Our goal is to construct [client endpoint path]/[additional path added by resolver]/[request path], so we just need to
- * strip the client endpoint path from the marshalled request path to isolate just the part added by the marshaller. Trailing
- * slash is removed from client endpoint path before stripping because it could cause the leading slash to be removed from the
- * request path: e.g., StringUtils.replaceOnce("/", "//test", "") generates "/test" and the expected result is "//test"
+ * Our goal is to construct [client endpoint path]/[additional path added by resolver]/[request path], so we just
+ * need to strip the client endpoint path from the marshalled request path to isolate just the part added by the
+ * marshaller. Trailing slash is removed from client endpoint path before stripping because it could cause the
+ * leading slash to be removed from the request path: e.g., StringUtils.replaceOnce("/", "//test", "") generates
+ * "/test" and the expected result is "//test"
*/
private static String combinePath(String clientEndpointPath, String requestPath, String resolvedUriPath) {
String requestPathWithClientPathRemoved = StringUtils.replaceOnce(requestPath, clientEndpointPath, "");
@@ -182,28 +178,6 @@ public final class AwsEndpointProviderUtils {
return finalPath;
}
- public static AwsRequest addHeaders(AwsRequest request, Map> headers) {
- AwsRequestOverrideConfiguration.Builder configBuilder = request.overrideConfiguration()
- .map(AwsRequestOverrideConfiguration::toBuilder).orElseGet(AwsRequestOverrideConfiguration::builder);
-
- headers.forEach((name, values) -> {
- List existingValues = configBuilder.headers().get(name);
- List updatedValues;
-
- if (existingValues != null) {
- updatedValues = new ArrayList<>(existingValues);
- } else {
- updatedValues = new ArrayList<>();
- }
-
- updatedValues.addAll(values);
-
- configBuilder.putHeader(name, updatedValues);
- });
-
- return request.toBuilder().overrideConfiguration(configBuilder.build()).build();
- }
-
private static void addKnownProperties(Endpoint.Builder builder, Map properties) {
properties.forEach((n, v) -> {
switch (n) {
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/ClientTestModels.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/ClientTestModels.java
index 69ab37c3315d..28903e5dedaf 100644
--- a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/ClientTestModels.java
+++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/ClientTestModels.java
@@ -17,7 +17,6 @@
import java.io.File;
-import org.eclipse.core.runtime.internal.adaptor.IModel;
import software.amazon.awssdk.codegen.C2jModels;
import software.amazon.awssdk.codegen.IntermediateModelBuilder;
import software.amazon.awssdk.codegen.model.config.customization.CustomizationConfig;
@@ -108,6 +107,158 @@ public static IntermediateModel queryServiceModels() {
return new IntermediateModelBuilder(models).build();
}
+ public static IntermediateModel queryServiceModelsEndpointAuthParamsWithAllowList() {
+ File serviceModel = new File(ClientTestModels.class.getResource("client/c2j/query/service-2.json").getFile());
+ File customizationModel =
+ new File(ClientTestModels.class.getResource("client/c2j/query/customization-endpoint-auth-params-with-allowed.config")
+ .getFile());
+ File waitersModel = new File(ClientTestModels.class.getResource("client/c2j/query/waiters-2.json").getFile());
+ File endpointRuleSetModel =
+ new File(ClientTestModels.class.getResource("client/c2j/query/endpoint-rule-set.json").getFile());
+ File endpointTestsModel =
+ new File(ClientTestModels.class.getResource("client/c2j/query/endpoint-tests.json").getFile());
+
+ C2jModels models = C2jModels
+ .builder()
+ .serviceModel(getServiceModel(serviceModel))
+ .customizationConfig(getCustomizationConfig(customizationModel))
+ .waitersModel(getWaiters(waitersModel))
+ .endpointRuleSetModel(getEndpointRuleSet(endpointRuleSetModel))
+ .endpointTestSuiteModel(getEndpointTestSuite(endpointTestsModel))
+ .build();
+
+ return new IntermediateModelBuilder(models).build();
+ }
+
+ public static IntermediateModel queryServiceModelsEndpointAuthParamsWithoutAllowList() {
+ File serviceModel = new File(ClientTestModels.class.getResource("client/c2j/query/service-2.json").getFile());
+ File customizationModel =
+ new File(ClientTestModels.class.getResource("client/c2j/query/customization-endpoint-auth-params-without-allowed"
+ + ".config")
+ .getFile());
+ File waitersModel = new File(ClientTestModels.class.getResource("client/c2j/query/waiters-2.json").getFile());
+ File endpointRuleSetModel =
+ new File(ClientTestModels.class.getResource("client/c2j/query/endpoint-rule-set.json").getFile());
+ File endpointTestsModel =
+ new File(ClientTestModels.class.getResource("client/c2j/query/endpoint-tests.json").getFile());
+
+ C2jModels models = C2jModels
+ .builder()
+ .serviceModel(getServiceModel(serviceModel))
+ .customizationConfig(getCustomizationConfig(customizationModel))
+ .waitersModel(getWaiters(waitersModel))
+ .endpointRuleSetModel(getEndpointRuleSet(endpointRuleSetModel))
+ .endpointTestSuiteModel(getEndpointTestSuite(endpointTestsModel))
+ .build();
+
+ return new IntermediateModelBuilder(models).build();
+ }
+
+ public static IntermediateModel granularAuthProvidersServiceModels() {
+ File serviceModel = new File(ClientTestModels.class.getResource("client/c2j/fine-grained-auth/service-2.json").getFile());
+ File customizationModel =
+ new File(ClientTestModels.class.getResource("client/c2j/fine-grained-auth/customization.config")
+ .getFile());
+
+ C2jModels models = C2jModels
+ .builder()
+ .serviceModel(getServiceModel(serviceModel))
+ .customizationConfig(getCustomizationConfig(customizationModel))
+ .build();
+
+ return new IntermediateModelBuilder(models).build();
+ }
+
+ public static IntermediateModel granularAuthWithLegacyTraitServiceModels() {
+ File serviceModel =
+ new File(ClientTestModels.class.getResource("client/c2j/fine-grained-auth-legacy-trait/service-2.json").getFile());
+ File customizationModel =
+ new File(ClientTestModels.class.getResource("client/c2j/fine-grained-auth-legacy-trait/customization.config")
+ .getFile());
+ C2jModels models = C2jModels
+ .builder()
+ .serviceModel(getServiceModel(serviceModel))
+ .customizationConfig(getCustomizationConfig(customizationModel))
+ .build();
+
+ return new IntermediateModelBuilder(models).build();
+ }
+
+ public static IntermediateModel allOperationsWithAuthSameValueServiceModels() {
+ File serviceModel =
+ new File(ClientTestModels.class.getResource("client/c2j/all-ops-with-auth-same-value/service-2.json").getFile());
+ File customizationModel =
+ new File(ClientTestModels.class.getResource("client/c2j/all-ops-with-auth-same-value/customization.config")
+ .getFile());
+ C2jModels models = C2jModels
+ .builder()
+ .serviceModel(getServiceModel(serviceModel))
+ .customizationConfig(getCustomizationConfig(customizationModel))
+ .build();
+
+ return new IntermediateModelBuilder(models).build();
+ }
+
+ public static IntermediateModel allOperationsWithAuthDifferentValueServiceModels() {
+ File serviceModel =
+ new File(ClientTestModels.class.getResource("client/c2j/all-ops-with-auth-different-value/service-2.json").getFile());
+ File customizationModel =
+ new File(ClientTestModels.class.getResource("client/c2j/all-ops-with-auth-different-value/customization.config")
+ .getFile());
+ C2jModels models = C2jModels
+ .builder()
+ .serviceModel(getServiceModel(serviceModel))
+ .customizationConfig(getCustomizationConfig(customizationModel))
+ .build();
+
+ return new IntermediateModelBuilder(models).build();
+ }
+
+ public static IntermediateModel operationWithNoAuth() {
+ File serviceModel =
+ new File(ClientTestModels.class.getResource("client/c2j/ops-with-no-auth/service-2.json").getFile());
+ File customizationModel =
+ new File(ClientTestModels.class.getResource("client/c2j/ops-with-no-auth/customization.config")
+ .getFile());
+ C2jModels models = C2jModels
+ .builder()
+ .serviceModel(getServiceModel(serviceModel))
+ .customizationConfig(getCustomizationConfig(customizationModel))
+ .build();
+
+ return new IntermediateModelBuilder(models).build();
+ }
+
+ public static IntermediateModel serviceWithNoAuth() {
+ File serviceModel =
+ new File(ClientTestModels.class.getResource("client/c2j/service-with-no-auth/service-2.json").getFile());
+ File customizationModel =
+ new File(ClientTestModels.class.getResource("client/c2j/service-with-no-auth/customization.config")
+ .getFile());
+ C2jModels models = C2jModels
+ .builder()
+ .serviceModel(getServiceModel(serviceModel))
+ .customizationConfig(getCustomizationConfig(customizationModel))
+ .build();
+
+ return new IntermediateModelBuilder(models).build();
+ }
+
+ public static IntermediateModel serviceMiniS3() {
+ File serviceModel =
+ new File(ClientTestModels.class.getResource("client/c2j/mini-s3/service-2.json").getFile());
+ File customizationModel =
+ new File(ClientTestModels.class.getResource("client/c2j/mini-s3/customization.config")
+ .getFile());
+ C2jModels models = C2jModels
+ .builder()
+ .serviceModel(getServiceModel(serviceModel))
+ .customizationConfig(getCustomizationConfig(customizationModel))
+ .build();
+
+ return new IntermediateModelBuilder(models).build();
+ }
+
public static IntermediateModel xmlServiceModels() {
File serviceModel = new File(ClientTestModels.class.getResource("client/c2j/xml/service-2.json").getFile());
File customizationModel = new File(ClientTestModels.class.getResource("client/c2j/xml/customization.config").getFile());
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeSpecTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeSpecTest.java
new file mode 100644
index 000000000000..15b061f9a835
--- /dev/null
+++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeSpecTest.java
@@ -0,0 +1,244 @@
+/*
+ * 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.codegen.poet.auth.scheme;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static software.amazon.awssdk.codegen.poet.PoetMatchers.generatesTo;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
+import software.amazon.awssdk.codegen.poet.ClassSpec;
+import software.amazon.awssdk.codegen.poet.ClientTestModels;
+
+public class AuthSchemeSpecTest {
+
+ @ParameterizedTest
+ @MethodSource("parameters")
+ void testCase(TestCase testCase) {
+ ClassSpec classSpec = testCase.classSpecProvider.apply(testCase.modelProvider.get());
+ String expectedFileName = testCase.caseName + "-auth-scheme-" + testCase.outputFileSuffix + ".java";
+ assertThat("Generated class must match " + expectedFileName,
+ classSpec, generatesTo(expectedFileName));
+ }
+
+ static List parameters() {
+ return Arrays.asList(
+ // query
+ TestCase.builder()
+ .modelProvider(ClientTestModels::queryServiceModels)
+ .classSpecProvider(AuthSchemeProviderSpec::new)
+ .caseName("query")
+ .outputFileSuffix("provider")
+ .build(),
+ TestCase.builder()
+ .modelProvider(ClientTestModels::queryServiceModels)
+ .classSpecProvider(AuthSchemeParamsSpec::new)
+ .caseName("query")
+ .outputFileSuffix("params")
+ .build(),
+ TestCase.builder()
+ .modelProvider(ClientTestModels::queryServiceModels)
+ .classSpecProvider(ModelBasedAuthSchemeProviderSpec::new)
+ .caseName("query")
+ .outputFileSuffix("default-provider")
+ .build(),
+ TestCase.builder()
+ .modelProvider(ClientTestModels::queryServiceModels)
+ .classSpecProvider(DefaultAuthSchemeParamsSpec::new)
+ .caseName("query")
+ .outputFileSuffix("default-params")
+ .build(),
+ // query-endpoint-auth-params
+ TestCase.builder()
+ .modelProvider(ClientTestModels::queryServiceModelsEndpointAuthParamsWithAllowList)
+ .classSpecProvider(AuthSchemeProviderSpec::new)
+ .caseName("query-endpoint-auth-params")
+ .outputFileSuffix("provider")
+ .build(),
+ // Endpoint based AuthScheme provider WITH allow list
+ // - Endpoint Provider
+ TestCase.builder()
+ .modelProvider(ClientTestModels::queryServiceModelsEndpointAuthParamsWithAllowList)
+ .classSpecProvider(EndpointBasedAuthSchemeProviderSpec::new)
+ .caseName("query-endpoint-auth-params")
+ .outputFileSuffix("endpoint-provider")
+ .build(),
+ // - Modeled provider
+ TestCase.builder()
+ .modelProvider(ClientTestModels::queryServiceModelsEndpointAuthParamsWithAllowList)
+ .classSpecProvider(ModelBasedAuthSchemeProviderSpec::new)
+ .caseName("query-endpoint-auth-params")
+ .outputFileSuffix("modeled-provider")
+ .build(),
+ // Endpoint based AuthScheme provider WITHOUT allow list
+ // - Endpoint Provider
+ TestCase.builder()
+ .modelProvider(ClientTestModels::queryServiceModelsEndpointAuthParamsWithoutAllowList)
+ .classSpecProvider(EndpointBasedAuthSchemeProviderSpec::new)
+ .caseName("query-endpoint-auth-params")
+ .outputFileSuffix("endpoint-provider-without-allowlist")
+ .build(),
+ // Auth scheme params from endpoint WITH allow list, MUST include ONLY the params in the allow list.
+ // - Interface
+ TestCase.builder()
+ .modelProvider(ClientTestModels::queryServiceModelsEndpointAuthParamsWithAllowList)
+ .classSpecProvider(AuthSchemeParamsSpec::new)
+ .caseName("query-endpoint-auth-params")
+ .outputFileSuffix("params-with-allowlist")
+ .build(),
+ // - Implementation
+ TestCase.builder()
+ .modelProvider(ClientTestModels::queryServiceModelsEndpointAuthParamsWithAllowList)
+ .classSpecProvider(DefaultAuthSchemeParamsSpec::new)
+ .caseName("query-endpoint-auth-params")
+ .outputFileSuffix("default-params-with-allowlist")
+ .build(),
+ // Auth scheme params from endpoint WITHOUT allow list, it MUST include all the endpoint params except for the
+ // default params.
+ // - Interface
+ TestCase.builder()
+ .modelProvider(ClientTestModels::queryServiceModelsEndpointAuthParamsWithoutAllowList)
+ .classSpecProvider(AuthSchemeParamsSpec::new)
+ .caseName("query-endpoint-auth-params")
+ .outputFileSuffix("params-without-allowlist")
+ .build(),
+ // - Implementation
+ TestCase.builder()
+ .modelProvider(ClientTestModels::queryServiceModelsEndpointAuthParamsWithoutAllowList)
+ .classSpecProvider(DefaultAuthSchemeParamsSpec::new)
+ .caseName("query-endpoint-auth-params")
+ .outputFileSuffix("default-params-without-allowlist")
+ .build(),
+ // Granular auth
+ TestCase.builder()
+ .modelProvider(ClientTestModels::granularAuthProvidersServiceModels)
+ .classSpecProvider(ModelBasedAuthSchemeProviderSpec::new)
+ .caseName("granular")
+ .outputFileSuffix("default-provider")
+ .build(),
+ // All operations with auth with the same values
+ TestCase.builder()
+ .modelProvider(ClientTestModels::allOperationsWithAuthSameValueServiceModels)
+ .classSpecProvider(ModelBasedAuthSchemeProviderSpec::new)
+ .caseName("all-ops-auth-same-value")
+ .outputFileSuffix("default-provider")
+ .build(),
+ // All operations with auth with different values
+ TestCase.builder()
+ .modelProvider(ClientTestModels::allOperationsWithAuthDifferentValueServiceModels)
+ .classSpecProvider(ModelBasedAuthSchemeProviderSpec::new)
+ .caseName("all-ops-auth-different-value")
+ .outputFileSuffix("default-provider")
+ .build(),
+ // Service with operations with auth none
+ TestCase.builder()
+ .modelProvider(ClientTestModels::operationWithNoAuth)
+ .classSpecProvider(ModelBasedAuthSchemeProviderSpec::new)
+ .caseName("ops-with-no-auth")
+ .outputFileSuffix("default-provider")
+ .build(),
+ // Service with signature version with the same value as S3
+ TestCase.builder()
+ .modelProvider(ClientTestModels::serviceMiniS3)
+ .classSpecProvider(ModelBasedAuthSchemeProviderSpec::new)
+ .caseName("mini-s3")
+ .outputFileSuffix("default-provider")
+ .build(),
+ TestCase.builder()
+ .modelProvider(ClientTestModels::granularAuthWithLegacyTraitServiceModels)
+ .classSpecProvider(ModelBasedAuthSchemeProviderSpec::new)
+ .caseName("auth-with-legacy-trait")
+ .outputFileSuffix("default-provider")
+ .build(),
+ // Interceptors
+ // - Normal case
+ TestCase.builder()
+ .modelProvider(ClientTestModels::queryServiceModels)
+ .classSpecProvider(AuthSchemeInterceptorSpec::new)
+ .caseName("query")
+ .outputFileSuffix("interceptor")
+ .build(),
+ // - Endpoints based params with allow list
+ TestCase.builder()
+ .modelProvider(ClientTestModels::queryServiceModelsEndpointAuthParamsWithAllowList)
+ .classSpecProvider(AuthSchemeInterceptorSpec::new)
+ .caseName("query-endpoint-auth-params-with-allowlist")
+ .outputFileSuffix("interceptor")
+ .build(),
+ // - Endpoints based params without allow list
+ TestCase.builder()
+ .modelProvider(ClientTestModels::queryServiceModelsEndpointAuthParamsWithoutAllowList)
+ .classSpecProvider(AuthSchemeInterceptorSpec::new)
+ .caseName("query-endpoint-auth-params-without-allowlist")
+ .outputFileSuffix("interceptor")
+ .build()
+ );
+ }
+
+ static class TestCase {
+ private final Supplier modelProvider;
+ private final Function classSpecProvider;
+ private final String outputFileSuffix;
+ private final String caseName;
+
+ TestCase(Builder builder) {
+ this.modelProvider = builder.modelProvider;
+ this.classSpecProvider = builder.classSpecProvider;
+ this.outputFileSuffix = builder.outputFileSuffix;
+ this.caseName = builder.caseName;
+ }
+
+ static Builder builder() {
+ return new Builder();
+ }
+
+ static class Builder {
+ private Supplier modelProvider;
+ private Function classSpecProvider;
+ private String outputFileSuffix;
+ private String caseName;
+
+ Builder modelProvider(Supplier modelProvider) {
+ this.modelProvider = modelProvider;
+ return this;
+ }
+
+ Builder classSpecProvider(Function classSpecProvider) {
+ this.classSpecProvider = classSpecProvider;
+ return this;
+ }
+
+ Builder outputFileSuffix(String outputFileSuffix) {
+ this.outputFileSuffix = outputFileSuffix;
+ return this;
+ }
+
+ Builder caseName(String caseName) {
+ this.caseName = caseName;
+ return this;
+ }
+
+ TestCase build() {
+ return new TestCase(this);
+ }
+ }
+ }
+}
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/builder/AsyncClientBuilderClassTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/builder/AsyncClientBuilderClassTest.java
new file mode 100644
index 000000000000..840ec2dbc13c
--- /dev/null
+++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/builder/AsyncClientBuilderClassTest.java
@@ -0,0 +1,39 @@
+/*
+ * 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.codegen.poet.builder;
+
+import static software.amazon.awssdk.codegen.poet.ClientTestModels.composedClientJsonServiceModels;
+import static software.amazon.awssdk.codegen.poet.ClientTestModels.restJsonServiceModels;
+import static software.amazon.awssdk.codegen.poet.builder.BuilderClassTestUtils.validateGeneration;
+
+import org.junit.jupiter.api.Test;
+
+/**
+ * Validate AsyncClientBuilderClass generation.
+ */
+public class AsyncClientBuilderClassTest {
+
+ @Test
+ public void asyncClientBuilderClass() {
+ validateGeneration(AsyncClientBuilderClass::new, restJsonServiceModels(), "test-async-client-builder-class.java");
+ }
+
+ @Test
+ public void asyncComposedClientBuilderClass() {
+ validateGeneration(AsyncClientBuilderClass::new, composedClientJsonServiceModels(),
+ "test-composed-async-client-builder-class.java");
+ }
+}
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/builder/AsyncClientBuilderInterfaceTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/builder/AsyncClientBuilderInterfaceTest.java
new file mode 100644
index 000000000000..63325fc21b25
--- /dev/null
+++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/builder/AsyncClientBuilderInterfaceTest.java
@@ -0,0 +1,32 @@
+/*
+ * 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.codegen.poet.builder;
+
+import static software.amazon.awssdk.codegen.poet.ClientTestModels.restJsonServiceModels;
+import static software.amazon.awssdk.codegen.poet.builder.BuilderClassTestUtils.validateGeneration;
+
+import org.junit.jupiter.api.Test;
+
+/**
+ * Validate AsyncClientBuilderInterface generation.
+ */
+public class AsyncClientBuilderInterfaceTest {
+
+ @Test
+ public void asyncClientBuilderInterface() {
+ validateGeneration(AsyncClientBuilderInterface::new, restJsonServiceModels(), "test-async-client-builder-interface.java");
+ }
+}
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/builder/BaseClientBuilderClassTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/builder/BaseClientBuilderClassTest.java
new file mode 100644
index 000000000000..ae6ea5a4df3c
--- /dev/null
+++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/builder/BaseClientBuilderClassTest.java
@@ -0,0 +1,84 @@
+/*
+ * 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.codegen.poet.builder;
+
+import static software.amazon.awssdk.codegen.poet.ClientTestModels.bearerAuthServiceModels;
+import static software.amazon.awssdk.codegen.poet.ClientTestModels.composedClientJsonServiceModels;
+import static software.amazon.awssdk.codegen.poet.ClientTestModels.internalConfigModels;
+import static software.amazon.awssdk.codegen.poet.ClientTestModels.operationWithNoAuth;
+import static software.amazon.awssdk.codegen.poet.ClientTestModels.queryServiceModels;
+import static software.amazon.awssdk.codegen.poet.ClientTestModels.queryServiceModelsEndpointAuthParamsWithAllowList;
+import static software.amazon.awssdk.codegen.poet.ClientTestModels.restJsonServiceModels;
+import static software.amazon.awssdk.codegen.poet.ClientTestModels.serviceWithNoAuth;
+import static software.amazon.awssdk.codegen.poet.builder.BuilderClassTestUtils.validateGeneration;
+
+import org.junit.jupiter.api.Test;
+import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
+
+/**
+ * Validate BaseClientBuilderClass generation.
+ */
+public class BaseClientBuilderClassTest {
+ @Test
+ public void baseClientBuilderClass() {
+ validateBaseClientBuilderClassGeneration(restJsonServiceModels(), "test-client-builder-class.java");
+ }
+
+ @Test
+ public void baseClientBuilderClassWithBearerAuth() {
+ validateBaseClientBuilderClassGeneration(bearerAuthServiceModels(), "test-bearer-auth-client-builder-class.java");
+ }
+
+ @Test
+ public void baseClientBuilderClassWithNoAuthOperation() {
+ validateBaseClientBuilderClassGeneration(operationWithNoAuth(), "test-no-auth-ops-client-builder-class.java");
+ }
+
+ @Test
+ public void baseClientBuilderClassWithNoAuthService() {
+ validateBaseClientBuilderClassGeneration(serviceWithNoAuth(), "test-no-auth-service-client-builder-class.java");
+ }
+
+ @Test
+ public void baseClientBuilderClassWithInternalUserAgent() {
+ validateBaseClientBuilderClassGeneration(internalConfigModels(), "test-client-builder-internal-defaults-class.java");
+ }
+
+ @Test
+ public void baseQueryClientBuilderClass() {
+ validateBaseClientBuilderClassGeneration(queryServiceModels(), "test-query-client-builder-class.java");
+ }
+
+ @Test
+ public void baseClientBuilderClassWithEndpointsAuthParams() {
+ validateBaseClientBuilderClassGeneration(queryServiceModelsEndpointAuthParamsWithAllowList(),
+ "test-client-builder-endpoints-auth-params.java");
+ }
+
+ @Test
+ public void syncComposedDefaultClientBuilderClass() {
+ validateBaseClientBuilderClassGeneration(composedClientJsonServiceModels(),
+ "test-composed-sync-default-client-builder.java");
+ }
+
+ private void validateBaseClientBuilderClassGeneration(IntermediateModel model, String expectedClassName) {
+ model.getCustomizationConfig().setUseSraAuth(false);
+ validateGeneration(BaseClientBuilderClass::new, model, expectedClassName);
+
+ model.getCustomizationConfig().setUseSraAuth(true);
+ validateGeneration(BaseClientBuilderClass::new, model, "sra/" + expectedClassName);
+ }
+}
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/builder/BaseClientBuilderInterfaceTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/builder/BaseClientBuilderInterfaceTest.java
new file mode 100644
index 000000000000..3839cb7bc3de
--- /dev/null
+++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/builder/BaseClientBuilderInterfaceTest.java
@@ -0,0 +1,49 @@
+/*
+ * 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.codegen.poet.builder;
+
+import static software.amazon.awssdk.codegen.poet.ClientTestModels.bearerAuthServiceModels;
+import static software.amazon.awssdk.codegen.poet.ClientTestModels.composedClientJsonServiceModels;
+import static software.amazon.awssdk.codegen.poet.ClientTestModels.restJsonServiceModels;
+import static software.amazon.awssdk.codegen.poet.builder.BuilderClassTestUtils.validateGeneration;
+
+import org.junit.jupiter.api.Test;
+import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
+
+/**
+ * Validate BaseClientBuilderInterface generation.
+ */
+public class BaseClientBuilderInterfaceTest {
+ @Test
+ public void baseClientBuilderInterface() {
+ validateBaseClientBuilderInterfaceGeneration(restJsonServiceModels(), "test-client-builder-interface.java");
+ }
+
+ @Test
+ public void baseClientBuilderInterfaceWithBearerAuth() {
+ validateBaseClientBuilderInterfaceGeneration(bearerAuthServiceModels(), "test-bearer-auth-client-builder-interface.java");
+ }
+
+ @Test
+ public void syncHasCrossRegionAccessEnabledPropertyBuilderClass() {
+ validateBaseClientBuilderInterfaceGeneration(composedClientJsonServiceModels(),
+ "test-customcontextparams-sync-client-builder-class.java");
+ }
+
+ private void validateBaseClientBuilderInterfaceGeneration(IntermediateModel model, String expectedClassName) {
+ validateGeneration(BaseClientBuilderInterface::new, model, expectedClassName);
+ }
+}
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/builder/BuilderClassTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/builder/BuilderClassTest.java
deleted file mode 100644
index a1fcfa98150e..000000000000
--- a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/builder/BuilderClassTest.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * 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.codegen.poet.builder;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static software.amazon.awssdk.codegen.poet.PoetMatchers.generatesTo;
-
-import java.util.function.Function;
-import org.junit.jupiter.api.Test;
-import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
-import software.amazon.awssdk.codegen.poet.ClassSpec;
-import software.amazon.awssdk.codegen.poet.ClientTestModels;
-
-/**
- * Validate client builder generation.
- */
-public class BuilderClassTest {
- @Test
- public void baseClientBuilderInterface() throws Exception {
- validateGeneration(BaseClientBuilderInterface::new, "test-client-builder-interface.java");
- }
-
- @Test
- public void baseClientBuilderClass() throws Exception {
- validateGeneration(BaseClientBuilderClass::new, "test-client-builder-class.java");
- }
-
- @Test
- public void baseClientBuilderInterfaceWithBearerAuthClass() throws Exception {
- validateBearerAuthGeneration(BaseClientBuilderInterface::new, "test-bearer-auth-client-builder-interface.java");
- }
-
- @Test
- public void baseClientBuilderWithBearerAuthClass() throws Exception {
- validateBearerAuthGeneration(BaseClientBuilderClass::new, "test-bearer-auth-client-builder-class.java");
- }
-
- @Test
- public void baseClientBuilderClassWithInternalUserAgent() throws Exception {
- assertThat(new BaseClientBuilderClass(ClientTestModels.internalConfigModels()), generatesTo("test-client-builder-internal-defaults-class.java"));
- }
-
- @Test
- public void baseQueryClientBuilderClass() throws Exception {
- validateQueryGeneration(BaseClientBuilderClass::new, "test-query-client-builder-class.java");
- }
-
- @Test
- public void syncClientBuilderInterface() throws Exception {
- validateGeneration(SyncClientBuilderInterface::new, "test-sync-client-builder-interface.java");
- }
-
- @Test
- public void syncClientBuilderClass() throws Exception {
- validateGeneration(SyncClientBuilderClass::new, "test-sync-client-builder-class.java");
- }
-
- @Test
- public void syncComposedClientBuilderClass() throws Exception {
- validateComposedClientGeneration(SyncClientBuilderClass::new, "test-composed-sync-client-builder-class.java");
- }
-
- @Test
- public void syncComposedDefaultClientBuilderClass() throws Exception {
- validateComposedClientGeneration(BaseClientBuilderClass::new, "test-composed-sync-default-client-builder.java");
- }
-
- @Test
- public void syncHasCrossRegionAccessEnabledPropertyBuilderClass() throws Exception {
- validateComposedClientGeneration(BaseClientBuilderInterface::new, "test-customcontextparams-sync-client-builder-class.java");
- }
-
-
- @Test
- public void asyncClientBuilderInterface() throws Exception {
- validateGeneration(AsyncClientBuilderInterface::new, "test-async-client-builder-interface.java");
- }
-
- @Test
- public void asyncClientBuilderClass() throws Exception {
- validateGeneration(AsyncClientBuilderClass::new, "test-async-client-builder-class.java");
- }
-
- @Test
- public void asyncComposedClientBuilderClass() throws Exception {
- validateComposedClientGeneration(AsyncClientBuilderClass::new, "test-composed-async-client-builder-class.java");
- }
-
- private void validateGeneration(Function generatorConstructor, String expectedClassName) {
- assertThat(generatorConstructor.apply(ClientTestModels.restJsonServiceModels()), generatesTo(expectedClassName));
- }
-
- private void validateComposedClientGeneration(Function generatorConstructor,
- String expectedClassName) {
- assertThat(generatorConstructor.apply(ClientTestModels.composedClientJsonServiceModels()), generatesTo(expectedClassName));
- }
-
- private void validateBearerAuthGeneration(Function generatorConstructor,
- String expectedClassName) {
- assertThat(generatorConstructor.apply(ClientTestModels.bearerAuthServiceModels()), generatesTo(expectedClassName));
- }
-
- private void validateQueryGeneration(Function generatorConstructor, String expectedClassName) {
- assertThat(generatorConstructor.apply(ClientTestModels.queryServiceModels()), generatesTo(expectedClassName));
- }
-}
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/builder/BuilderClassTestUtils.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/builder/BuilderClassTestUtils.java
new file mode 100644
index 000000000000..7aaf463d7797
--- /dev/null
+++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/builder/BuilderClassTestUtils.java
@@ -0,0 +1,31 @@
+/*
+ * 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.codegen.poet.builder;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static software.amazon.awssdk.codegen.poet.PoetMatchers.generatesTo;
+
+import java.util.function.Function;
+import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
+import software.amazon.awssdk.codegen.poet.ClassSpec;
+
+public class BuilderClassTestUtils {
+ static void validateGeneration(Function generatorConstructor,
+ IntermediateModel model,
+ String expectedClassName) {
+ assertThat(generatorConstructor.apply(model), generatesTo(expectedClassName));
+ }
+}
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/builder/SyncClientBuilderClassTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/builder/SyncClientBuilderClassTest.java
new file mode 100644
index 000000000000..fd95f40c4975
--- /dev/null
+++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/builder/SyncClientBuilderClassTest.java
@@ -0,0 +1,38 @@
+/*
+ * 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.codegen.poet.builder;
+
+import static software.amazon.awssdk.codegen.poet.ClientTestModels.composedClientJsonServiceModels;
+import static software.amazon.awssdk.codegen.poet.ClientTestModels.restJsonServiceModels;
+import static software.amazon.awssdk.codegen.poet.builder.BuilderClassTestUtils.validateGeneration;
+
+import org.junit.jupiter.api.Test;
+
+/**
+ * Validate SyncClientBuilderClass generation.
+ */
+public class SyncClientBuilderClassTest {
+ @Test
+ public void syncClientBuilderClass() {
+ validateGeneration(SyncClientBuilderClass::new, restJsonServiceModels(), "test-sync-client-builder-class.java");
+ }
+
+ @Test
+ public void syncComposedClientBuilderClass() {
+ validateGeneration(SyncClientBuilderClass::new, composedClientJsonServiceModels(),
+ "test-composed-sync-client-builder-class.java");
+ }
+}
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/builder/SyncClientBuilderInterfaceTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/builder/SyncClientBuilderInterfaceTest.java
new file mode 100644
index 000000000000..5289c71ecfe4
--- /dev/null
+++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/builder/SyncClientBuilderInterfaceTest.java
@@ -0,0 +1,31 @@
+/*
+ * 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.codegen.poet.builder;
+
+import static software.amazon.awssdk.codegen.poet.ClientTestModels.restJsonServiceModels;
+import static software.amazon.awssdk.codegen.poet.builder.BuilderClassTestUtils.validateGeneration;
+
+import org.junit.jupiter.api.Test;
+
+/**
+ * Validate SyncClientBuilderInterface generation.
+ */
+public class SyncClientBuilderInterfaceTest {
+ @Test
+ public void syncClientBuilderInterface() {
+ validateGeneration(SyncClientBuilderInterface::new, restJsonServiceModels(), "test-sync-client-builder-interface.java");
+ }
+}
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/AsyncClientClassTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/AsyncClientClassTest.java
new file mode 100644
index 000000000000..d2c177051493
--- /dev/null
+++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/AsyncClientClassTest.java
@@ -0,0 +1,95 @@
+/*
+ * 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.codegen.poet.client;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static software.amazon.awssdk.codegen.poet.ClientTestModels.awsJsonServiceModels;
+import static software.amazon.awssdk.codegen.poet.ClientTestModels.awsQueryCompatibleJsonServiceModels;
+import static software.amazon.awssdk.codegen.poet.ClientTestModels.customContentTypeModels;
+import static software.amazon.awssdk.codegen.poet.ClientTestModels.endpointDiscoveryModels;
+import static software.amazon.awssdk.codegen.poet.ClientTestModels.queryServiceModels;
+import static software.amazon.awssdk.codegen.poet.ClientTestModels.restJsonServiceModels;
+import static software.amazon.awssdk.codegen.poet.ClientTestModels.xmlServiceModels;
+import static software.amazon.awssdk.codegen.poet.PoetMatchers.generatesTo;
+
+import org.junit.Test;
+import software.amazon.awssdk.codegen.emitters.GeneratorTaskParams;
+import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
+
+public class AsyncClientClassTest {
+ @Test
+ public void asyncClientClassRestJson() {
+ AsyncClientClass asyncClientClass = createAsyncClientClass(restJsonServiceModels(), false);
+ assertThat(asyncClientClass, generatesTo("test-json-async-client-class.java"));
+
+ AsyncClientClass sraAsyncClientClass = createAsyncClientClass(restJsonServiceModels(), true);
+ assertThat(sraAsyncClientClass, generatesTo("sra/test-json-async-client-class.java"));
+ }
+
+ @Test
+ public void asyncClientClassQuery() {
+ AsyncClientClass asyncClientClass = createAsyncClientClass(queryServiceModels(), false);
+ assertThat(asyncClientClass, generatesTo("test-query-async-client-class.java"));
+
+ AsyncClientClass sraAsyncClientClass = createAsyncClientClass(queryServiceModels(), true);
+ assertThat(sraAsyncClientClass, generatesTo("sra/test-query-async-client-class.java"));
+ }
+
+ @Test
+ public void asyncClientClassAwsJson() {
+ AsyncClientClass asyncClientClass = createAsyncClientClass(awsJsonServiceModels(), false);
+ assertThat(asyncClientClass, generatesTo("test-aws-json-async-client-class.java"));
+
+ AsyncClientClass sraAsyncClientClass = createAsyncClientClass(awsJsonServiceModels(), true);
+ assertThat(sraAsyncClientClass, generatesTo("sra/test-aws-json-async-client-class.java"));
+ }
+
+ @Test
+ public void asyncClientClassAwsQueryCompatibleJson() {
+ AsyncClientClass asyncClientClass = createAsyncClientClass(awsQueryCompatibleJsonServiceModels());
+ assertThat(asyncClientClass, generatesTo("test-aws-query-compatible-json-async-client-class.java"));
+ }
+
+ @Test
+ public void asyncClientClassXml() {
+ AsyncClientClass asyncClientClass = createAsyncClientClass(xmlServiceModels(), false);
+ assertThat(asyncClientClass, generatesTo("test-xml-async-client-class.java"));
+
+ AsyncClientClass sraAsyncClientClass = createAsyncClientClass(xmlServiceModels(), true);
+ assertThat(sraAsyncClientClass, generatesTo("sra/test-xml-async-client-class.java"));
+ }
+
+ @Test
+ public void asyncClientEndpointDiscovery() {
+ AsyncClientClass asyncClientEndpointDiscovery = createAsyncClientClass(endpointDiscoveryModels());
+ assertThat(asyncClientEndpointDiscovery, generatesTo("test-endpoint-discovery-async.java"));
+ }
+
+ @Test
+ public void asyncClientCustomServiceMetaData() {
+ AsyncClientClass asyncClientCustomServiceMetaData = createAsyncClientClass(customContentTypeModels());
+ assertThat(asyncClientCustomServiceMetaData, generatesTo("test-customservicemetadata-async.java"));
+ }
+
+ private AsyncClientClass createAsyncClientClass(IntermediateModel model) {
+ return new AsyncClientClass(GeneratorTaskParams.create(model, "sources/", "tests/", "resources/"));
+ }
+
+ private AsyncClientClass createAsyncClientClass(IntermediateModel model, boolean useSraAuth) {
+ model.getCustomizationConfig().setUseSraAuth(useSraAuth);
+ return createAsyncClientClass(model);
+ }
+}
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/EndpointAuthSchemeInterceptorClassSpecTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/AsyncClientInterfaceTest.java
similarity index 61%
rename from codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/EndpointAuthSchemeInterceptorClassSpecTest.java
rename to codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/AsyncClientInterfaceTest.java
index 99d4a3b4bf3e..2ab2aa389716 100644
--- a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/EndpointAuthSchemeInterceptorClassSpecTest.java
+++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/AsyncClientInterfaceTest.java
@@ -13,20 +13,19 @@
* permissions and limitations under the License.
*/
-package software.amazon.awssdk.codegen.poet.rules;
+package software.amazon.awssdk.codegen.poet.client;
import static org.hamcrest.MatcherAssert.assertThat;
+import static software.amazon.awssdk.codegen.poet.ClientTestModels.restJsonServiceModels;
import static software.amazon.awssdk.codegen.poet.PoetMatchers.generatesTo;
-import org.junit.jupiter.api.Test;
+import org.junit.Test;
import software.amazon.awssdk.codegen.poet.ClassSpec;
-import software.amazon.awssdk.codegen.poet.ClientTestModels;
-
-public class EndpointAuthSchemeInterceptorClassSpecTest {
+public class AsyncClientInterfaceTest {
@Test
- public void endpointAuthSchemeInterceptor() {
- ClassSpec endpointAuthSchemeInterceptor = new EndpointAuthSchemeInterceptorClassSpec(ClientTestModels.queryServiceModels());
- assertThat(endpointAuthSchemeInterceptor, generatesTo("endpoint-auth-scheme-interceptor.java"));
+ public void asyncClientInterface() {
+ ClassSpec asyncClientInterface = new AsyncClientInterface(restJsonServiceModels());
+ assertThat(asyncClientInterface, generatesTo("test-json-async-client-interface.java"));
}
}
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/DelegatingAsyncClientClassTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/DelegatingAsyncClientClassTest.java
new file mode 100644
index 000000000000..a12ab3ac659c
--- /dev/null
+++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/DelegatingAsyncClientClassTest.java
@@ -0,0 +1,31 @@
+/*
+ * 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.codegen.poet.client;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static software.amazon.awssdk.codegen.poet.ClientTestModels.restJsonServiceModels;
+import static software.amazon.awssdk.codegen.poet.PoetMatchers.generatesTo;
+
+import org.junit.Test;
+
+public class DelegatingAsyncClientClassTest {
+ @Test
+ public void delegatingAsyncClientClass() {
+ DelegatingAsyncClientClass asyncClientDecoratorAbstractClass =
+ new DelegatingAsyncClientClass(restJsonServiceModels());
+ assertThat(asyncClientDecoratorAbstractClass, generatesTo("test-abstract-async-client-class.java"));
+ }
+}
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/DelegatingSyncClientClassTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/DelegatingSyncClientClassTest.java
new file mode 100644
index 000000000000..bfa9f0005dfa
--- /dev/null
+++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/DelegatingSyncClientClassTest.java
@@ -0,0 +1,31 @@
+/*
+ * 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.codegen.poet.client;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static software.amazon.awssdk.codegen.poet.ClientTestModels.restJsonServiceModels;
+import static software.amazon.awssdk.codegen.poet.PoetMatchers.generatesTo;
+
+import org.junit.Test;
+
+public class DelegatingSyncClientClassTest {
+ @Test
+ public void delegatingSyncClientClass() {
+ DelegatingSyncClientClass syncClientDecoratorAbstractClass =
+ new DelegatingSyncClientClass(restJsonServiceModels());
+ assertThat(syncClientDecoratorAbstractClass, generatesTo("test-abstract-sync-client-class.java"));
+ }
+}
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/PoetClientFunctionalTests.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/PoetClientFunctionalTests.java
deleted file mode 100644
index c23890c2d499..000000000000
--- a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/PoetClientFunctionalTests.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * 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.codegen.poet.client;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static software.amazon.awssdk.codegen.poet.PoetMatchers.generatesTo;
-
-import org.junit.Test;
-import software.amazon.awssdk.codegen.emitters.GeneratorTaskParams;
-import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
-import software.amazon.awssdk.codegen.poet.ClassSpec;
-import software.amazon.awssdk.codegen.poet.ClientTestModels;
-
-public class PoetClientFunctionalTests {
- @Test
- public void asyncClientClassRestJson() throws Exception {
- AsyncClientClass asyncClientClass = createAsyncClientClass(ClientTestModels.restJsonServiceModels());
- assertThat(asyncClientClass, generatesTo("test-json-async-client-class.java"));
- }
-
- @Test
- public void asyncClientInterface() throws Exception {
- ClassSpec asyncClientInterface = new AsyncClientInterface(ClientTestModels.restJsonServiceModels());
- assertThat(asyncClientInterface, generatesTo("test-json-async-client-interface.java"));
- }
-
- @Test
- public void delegatingAsyncClientClass() throws Exception {
- DelegatingAsyncClientClass asyncClientDecoratorAbstractClass =
- new DelegatingAsyncClientClass(ClientTestModels.restJsonServiceModels());
- assertThat(asyncClientDecoratorAbstractClass, generatesTo("test-abstract-async-client-class.java"));
- }
-
- @Test
- public void syncClientInterface() throws Exception {
- ClassSpec syncClientInterface = new SyncClientInterface(ClientTestModels.restJsonServiceModels());
- assertThat(syncClientInterface, generatesTo("test-json-client-interface.java"));
- }
-
- @Test
- public void delegatingSyncClientClass() throws Exception {
- DelegatingSyncClientClass syncClientDecoratorAbstractClass =
- new DelegatingSyncClientClass(ClientTestModels.restJsonServiceModels());
- assertThat(syncClientDecoratorAbstractClass, generatesTo("test-abstract-sync-client-class.java"));
- }
-
- @Test
- public void syncClientClassRestJson() throws Exception {
- SyncClientClass syncClientClass = createSyncClientClass(ClientTestModels.restJsonServiceModels());
- assertThat(syncClientClass, generatesTo("test-json-client-class.java"));
- }
-
- @Test
- public void syncClientClassQuery() throws Exception {
- SyncClientClass syncClientClass = createSyncClientClass(ClientTestModels.queryServiceModels());
- assertThat(syncClientClass, generatesTo("test-query-client-class.java"));
- }
-
- @Test
- public void asyncClientClassQuery() throws Exception {
- AsyncClientClass syncClientClass = createAsyncClientClass(ClientTestModels.queryServiceModels());
- assertThat(syncClientClass, generatesTo("test-query-async-client-class.java"));
- }
-
- @Test
- public void asyncClientClassAwsJson() throws Exception {
- AsyncClientClass asyncClientClass = createAsyncClientClass(ClientTestModels.awsJsonServiceModels());
- assertThat(asyncClientClass, generatesTo("test-aws-json-async-client-class.java"));
- }
-
- @Test
- public void asyncClientClassAwsQueryCompatibleJson() throws Exception {
- AsyncClientClass asyncClientClass = createAsyncClientClass(ClientTestModels.awsQueryCompatibleJsonServiceModels());
- assertThat(asyncClientClass, generatesTo("test-aws-query-compatible-json-async-client-class.java"));
- }
-
- @Test
- public void syncClientClassAwsQueryCompatibleJson() throws Exception {
- SyncClientClass syncClientClass = createSyncClientClass(ClientTestModels.awsQueryCompatibleJsonServiceModels());
- assertThat(syncClientClass, generatesTo("test-aws-query-compatible-json-sync-client-class.java"));
- }
-
- @Test
- public void syncClientClassXml() throws Exception {
- SyncClientClass syncClientClass = createSyncClientClass(ClientTestModels.xmlServiceModels());
- assertThat(syncClientClass, generatesTo("test-xml-client-class.java"));
- }
-
- @Test
- public void asyncClientClassXml() throws Exception {
- AsyncClientClass syncClientClass = createAsyncClientClass(ClientTestModels.xmlServiceModels());
- assertThat(syncClientClass, generatesTo("test-xml-async-client-class.java"));
- }
-
- private SyncClientClass createSyncClientClass(IntermediateModel model) {
- return new SyncClientClass(GeneratorTaskParams.create(model, "sources/", "tests/", "resources/"));
- }
-
- private AsyncClientClass createAsyncClientClass(IntermediateModel model) {
- return new AsyncClientClass(GeneratorTaskParams.create(model, "sources/", "tests/", "resources/"));
- }
-
- @Test
- public void syncClientEndpointDiscovery() throws Exception {
- ClassSpec syncClientEndpointDiscovery = createSyncClientClass(ClientTestModels.endpointDiscoveryModels());
- assertThat(syncClientEndpointDiscovery, generatesTo("test-endpoint-discovery-sync.java"));
- }
-
- @Test
- public void asyncClientEndpointDiscovery() throws Exception {
- ClassSpec asyncClientEndpointDiscovery = new AsyncClientClass(
- GeneratorTaskParams.create(ClientTestModels.endpointDiscoveryModels(), "sources/", "tests/", "resources/"));
- assertThat(asyncClientEndpointDiscovery, generatesTo("test-endpoint-discovery-async.java"));
- }
-
- @Test
- public void asyncClientCustomServiceMetaData() throws Exception {
- ClassSpec asyncClientCustomServiceMetaData = new AsyncClientClass(
- GeneratorTaskParams.create(ClientTestModels.customContentTypeModels(), "sources/", "tests/", "resources/"));
- assertThat(asyncClientCustomServiceMetaData, generatesTo("test-customservicemetadata-async.java"));
- }
-
- @Test
- public void syncClientCustomServiceMetaData() throws Exception {
- ClassSpec syncClientCustomServiceMetaData = createSyncClientClass(ClientTestModels.customContentTypeModels());
- assertThat(syncClientCustomServiceMetaData, generatesTo("test-customservicemetadata-sync.java"));
- }
-}
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/SyncClientClassTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/SyncClientClassTest.java
new file mode 100644
index 000000000000..8f40dbd3a7d4
--- /dev/null
+++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/SyncClientClassTest.java
@@ -0,0 +1,86 @@
+/*
+ * 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.codegen.poet.client;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static software.amazon.awssdk.codegen.poet.ClientTestModels.awsQueryCompatibleJsonServiceModels;
+import static software.amazon.awssdk.codegen.poet.ClientTestModels.customContentTypeModels;
+import static software.amazon.awssdk.codegen.poet.ClientTestModels.endpointDiscoveryModels;
+import static software.amazon.awssdk.codegen.poet.ClientTestModels.queryServiceModels;
+import static software.amazon.awssdk.codegen.poet.ClientTestModels.restJsonServiceModels;
+import static software.amazon.awssdk.codegen.poet.ClientTestModels.xmlServiceModels;
+import static software.amazon.awssdk.codegen.poet.PoetMatchers.generatesTo;
+
+import org.junit.Test;
+import software.amazon.awssdk.codegen.emitters.GeneratorTaskParams;
+import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
+import software.amazon.awssdk.codegen.poet.ClassSpec;
+
+public class SyncClientClassTest {
+ @Test
+ public void syncClientClassRestJson() {
+ SyncClientClass syncClientClass = createSyncClientClass(restJsonServiceModels(), false);
+ assertThat(syncClientClass, generatesTo("test-json-client-class.java"));
+
+ SyncClientClass sraSyncClientClass = createSyncClientClass(restJsonServiceModels(), true);
+ assertThat(sraSyncClientClass, generatesTo("sra/test-json-client-class.java"));
+ }
+
+ @Test
+ public void syncClientClassQuery() {
+ SyncClientClass syncClientClass = createSyncClientClass(queryServiceModels(), false);
+ assertThat(syncClientClass, generatesTo("test-query-client-class.java"));
+
+ SyncClientClass sraSyncClientClass = createSyncClientClass(queryServiceModels(), true);
+ assertThat(sraSyncClientClass, generatesTo("sra/test-query-client-class.java"));
+ }
+
+ @Test
+ public void syncClientClassAwsQueryCompatibleJson() {
+ SyncClientClass syncClientClass = createSyncClientClass(awsQueryCompatibleJsonServiceModels());
+ assertThat(syncClientClass, generatesTo("test-aws-query-compatible-json-sync-client-class.java"));
+ }
+
+ @Test
+ public void syncClientClassXml() {
+ SyncClientClass syncClientClass = createSyncClientClass(xmlServiceModels(), false);
+ assertThat(syncClientClass, generatesTo("test-xml-client-class.java"));
+
+ SyncClientClass sraSyncClientClass = createSyncClientClass(xmlServiceModels(), true);
+ assertThat(sraSyncClientClass, generatesTo("sra/test-xml-client-class.java"));
+ }
+
+ @Test
+ public void syncClientEndpointDiscovery() {
+ ClassSpec syncClientEndpointDiscovery = createSyncClientClass(endpointDiscoveryModels());
+ assertThat(syncClientEndpointDiscovery, generatesTo("test-endpoint-discovery-sync.java"));
+ }
+
+ @Test
+ public void syncClientCustomServiceMetaData() {
+ ClassSpec syncClientCustomServiceMetaData = createSyncClientClass(customContentTypeModels());
+ assertThat(syncClientCustomServiceMetaData, generatesTo("test-customservicemetadata-sync.java"));
+ }
+
+ private SyncClientClass createSyncClientClass(IntermediateModel model) {
+ return new SyncClientClass(GeneratorTaskParams.create(model, "sources/", "tests/", "resources/"));
+ }
+
+ private SyncClientClass createSyncClientClass(IntermediateModel model, boolean useSraAuth) {
+ model.getCustomizationConfig().setUseSraAuth(useSraAuth);
+ return createSyncClientClass(model);
+ }
+}
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/SyncClientInterfaceTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/SyncClientInterfaceTest.java
new file mode 100644
index 000000000000..2e074970cb34
--- /dev/null
+++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/SyncClientInterfaceTest.java
@@ -0,0 +1,31 @@
+/*
+ * 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.codegen.poet.client;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static software.amazon.awssdk.codegen.poet.ClientTestModels.restJsonServiceModels;
+import static software.amazon.awssdk.codegen.poet.PoetMatchers.generatesTo;
+
+import org.junit.Test;
+import software.amazon.awssdk.codegen.poet.ClassSpec;
+
+public class SyncClientInterfaceTest {
+ @Test
+ public void syncClientInterface() {
+ ClassSpec syncClientInterface = new SyncClientInterface(restJsonServiceModels());
+ assertThat(syncClientInterface, generatesTo("test-json-client-interface.java"));
+ }
+}
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/model/ServiceClientConfigurationBuilderSpecTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/model/ServiceClientConfigurationBuilderSpecTest.java
new file mode 100644
index 000000000000..ea30f4f02e75
--- /dev/null
+++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/model/ServiceClientConfigurationBuilderSpecTest.java
@@ -0,0 +1,55 @@
+/*
+ * 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.codegen.poet.model;
+
+import static software.amazon.awssdk.codegen.poet.PoetMatchers.generatesTo;
+
+import java.io.File;
+import java.io.IOException;
+import org.hamcrest.MatcherAssert;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import software.amazon.awssdk.codegen.C2jModels;
+import software.amazon.awssdk.codegen.IntermediateModelBuilder;
+import software.amazon.awssdk.codegen.model.config.customization.CustomizationConfig;
+import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
+import software.amazon.awssdk.codegen.model.service.ServiceModel;
+import software.amazon.awssdk.codegen.utils.ModelLoaderUtils;
+
+public class ServiceClientConfigurationBuilderSpecTest {
+ private static IntermediateModel intermediateModel;
+
+ @BeforeAll
+ public static void setUp() throws IOException {
+ File serviceModelFile = new File(AwsModelSpecTest.class.getResource("service-2.json").getFile());
+ File customizationConfigFile = new File(AwsModelSpecTest.class
+ .getResource("customization.config")
+ .getFile());
+
+ intermediateModel = new IntermediateModelBuilder(
+ C2jModels.builder()
+ .serviceModel(ModelLoaderUtils.loadModel(ServiceModel.class, serviceModelFile))
+ .customizationConfig(ModelLoaderUtils.loadModel(CustomizationConfig.class, customizationConfigFile))
+ .build())
+ .build();
+ }
+
+ @Test
+ public void testGeneration() {
+ ServiceClientConfigurationBuilderClass spec = new ServiceClientConfigurationBuilderClass(intermediateModel);
+ MatcherAssert.assertThat(spec, generatesTo("serviceclientconfiguration-builder.java"));
+ }
+}
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/EndpointResolverInterceptorSpecTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/EndpointResolverInterceptorSpecTest.java
index 8ef78e35fb52..f3cf566962d1 100644
--- a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/EndpointResolverInterceptorSpecTest.java
+++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/EndpointResolverInterceptorSpecTest.java
@@ -19,13 +19,27 @@
import static software.amazon.awssdk.codegen.poet.PoetMatchers.generatesTo;
import org.junit.jupiter.api.Test;
+import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
import software.amazon.awssdk.codegen.poet.ClassSpec;
import software.amazon.awssdk.codegen.poet.ClientTestModels;
public class EndpointResolverInterceptorSpecTest {
@Test
public void endpointResolverInterceptorClass() {
- ClassSpec endpointProviderInterceptor = new EndpointResolverInterceptorSpec(ClientTestModels.queryServiceModels());
+ ClassSpec endpointProviderInterceptor = new EndpointResolverInterceptorSpec(getModel(true));
assertThat(endpointProviderInterceptor, generatesTo("endpoint-resolve-interceptor.java"));
}
+
+ // TODO(post-sra-identity-auth): This can be deleted when useSraAuth is removed
+ @Test
+ public void endpointResolverInterceptorClass_preSra() {
+ ClassSpec endpointProviderInterceptor = new EndpointResolverInterceptorSpec(getModel(false));
+ assertThat(endpointProviderInterceptor, generatesTo("endpoint-resolve-interceptor-preSra.java"));
+ }
+
+ private static IntermediateModel getModel(boolean useSraAuth) {
+ IntermediateModel model = ClientTestModels.queryServiceModels();
+ model.getCustomizationConfig().setUseSraAuth(useSraAuth);
+ return model;
+ }
}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/all-ops-auth-different-value-auth-scheme-default-provider.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/all-ops-auth-different-value-auth-scheme-default-provider.java
new file mode 100644
index 000000000000..03fed694330c
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/all-ops-auth-different-value-auth-scheme-default-provider.java
@@ -0,0 +1,67 @@
+/*
+ * 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.services.database.auth.scheme.internal;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import software.amazon.awssdk.annotations.Generated;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.http.auth.aws.signer.AwsV4HttpSigner;
+import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption;
+import software.amazon.awssdk.services.database.auth.scheme.DatabaseAuthSchemeParams;
+import software.amazon.awssdk.services.database.auth.scheme.DatabaseAuthSchemeProvider;
+
+@Generated("software.amazon.awssdk:codegen")
+@SdkInternalApi
+public final class DefaultDatabaseAuthSchemeProvider implements DatabaseAuthSchemeProvider {
+ private static final DefaultDatabaseAuthSchemeProvider DEFAULT = new DefaultDatabaseAuthSchemeProvider();
+
+ private DefaultDatabaseAuthSchemeProvider() {
+ }
+
+ public static DefaultDatabaseAuthSchemeProvider create() {
+ return DEFAULT;
+ }
+
+ @Override
+ public List resolveAuthScheme(DatabaseAuthSchemeParams params) {
+ List options = new ArrayList<>();
+ switch (params.operation()) {
+ case "DeleteRow":
+ options.add(AuthSchemeOption.builder().schemeId("smithy.api#httpBearerAuth").build());
+ options.add(AuthSchemeOption.builder().schemeId("aws.auth#sigv4")
+ .putSignerProperty(AwsV4HttpSigner.SERVICE_SIGNING_NAME, "database-service")
+ .putSignerProperty(AwsV4HttpSigner.REGION_NAME, params.region().id()).build());
+ break;
+ case "GetRow":
+ options.add(AuthSchemeOption.builder().schemeId("smithy.api#httpBearerAuth").build());
+ break;
+ case "PutRow":
+ options.add(AuthSchemeOption.builder().schemeId("aws.auth#sigv4")
+ .putSignerProperty(AwsV4HttpSigner.SERVICE_SIGNING_NAME, "database-service")
+ .putSignerProperty(AwsV4HttpSigner.REGION_NAME, params.region().id()).build());
+ break;
+ default:
+ options.add(AuthSchemeOption.builder().schemeId("aws.auth#sigv4")
+ .putSignerProperty(AwsV4HttpSigner.SERVICE_SIGNING_NAME, "database-service")
+ .putSignerProperty(AwsV4HttpSigner.REGION_NAME, params.region().id()).build());
+ options.add(AuthSchemeOption.builder().schemeId("smithy.api#httpBearerAuth").build());
+ break;
+ }
+ return Collections.unmodifiableList(options);
+ }
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/all-ops-auth-same-value-auth-scheme-default-provider.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/all-ops-auth-same-value-auth-scheme-default-provider.java
new file mode 100644
index 000000000000..b1ced5712b19
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/all-ops-auth-same-value-auth-scheme-default-provider.java
@@ -0,0 +1,49 @@
+/*
+ * 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.services.database.auth.scheme.internal;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import software.amazon.awssdk.annotations.Generated;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.http.auth.aws.signer.AwsV4HttpSigner;
+import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption;
+import software.amazon.awssdk.services.database.auth.scheme.DatabaseAuthSchemeParams;
+import software.amazon.awssdk.services.database.auth.scheme.DatabaseAuthSchemeProvider;
+
+@Generated("software.amazon.awssdk:codegen")
+@SdkInternalApi
+public final class DefaultDatabaseAuthSchemeProvider implements DatabaseAuthSchemeProvider {
+ private static final DefaultDatabaseAuthSchemeProvider DEFAULT = new DefaultDatabaseAuthSchemeProvider();
+
+ private DefaultDatabaseAuthSchemeProvider() {
+ }
+
+ public static DefaultDatabaseAuthSchemeProvider create() {
+ return DEFAULT;
+ }
+
+ @Override
+ public List resolveAuthScheme(DatabaseAuthSchemeParams params) {
+ List options = new ArrayList<>();
+ options.add(AuthSchemeOption.builder().schemeId("aws.auth#sigv4")
+ .putSignerProperty(AwsV4HttpSigner.SERVICE_SIGNING_NAME, "database-service")
+ .putSignerProperty(AwsV4HttpSigner.REGION_NAME, params.region().id()).build());
+ options.add(AuthSchemeOption.builder().schemeId("smithy.api#httpBearerAuth").build());
+ return Collections.unmodifiableList(options);
+ }
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/auth-scheme-params.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/auth-scheme-params.java
new file mode 100644
index 000000000000..9bbc556dbe27
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/auth-scheme-params.java
@@ -0,0 +1,67 @@
+/*
+ * 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.services.query.auth.scheme;
+
+import java.util.Optional;
+import software.amazon.awssdk.annotations.Generated;
+import software.amazon.awssdk.annotations.SdkPublicApi;
+import software.amazon.awssdk.services.query.auth.scheme.internal.DefaultQueryAuthSchemeParams;
+
+/**
+ * The parameters object used to resolve the auth schemes for the Query service.
+ */
+@Generated("software.amazon.awssdk:codegen")
+@SdkPublicApi
+public interface QueryAuthSchemeParams {
+
+ /**
+ * Get a new builder for creating a {@link QueryAuthSchemeParams}.
+ */
+ static Builder builder() {
+ return DefaultQueryAuthSchemeParams.builder();
+ }
+
+ /**
+ * Returns the operation for which to resolve the auth scheme.
+ */
+ String operation();
+
+ /**
+ * Returns the region. The region is optional. The region parameter may be used with "aws.auth#sigv4" auth scheme.
+ * By default, the region will be empty.
+ */
+ Optional region();
+
+ /**
+ * A builder for a {@link QueryAuthSchemeParams}.
+ */
+ interface Builder {
+ /**
+ * Set the operation for which to resolve the auth scheme.
+ */
+ Builder operation(String operation);
+
+ /**
+ * Set the region. The region parameter may be used with the "aws.auth#sigv4" auth scheme.
+ */
+ Builder region(String region);
+
+ /**
+ * Returns a {@link QueryAuthSchemeParams} object that is created from the properties that have been set on the builder.
+ */
+ QueryAuthSchemeParams build();
+ }
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/auth-scheme-provider.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/auth-scheme-provider.java
new file mode 100644
index 000000000000..a4f84dc2665a
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/auth-scheme-provider.java
@@ -0,0 +1,53 @@
+/*
+ * 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.services.query.auth.scheme;
+
+import java.util.List;
+import java.util.function.Consumer;
+import software.amazon.awssdk.annotations.Generated;
+import software.amazon.awssdk.annotations.SdkPublicApi;
+import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption;
+import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeProvider;
+import software.amazon.awssdk.services.query.auth.scheme.internal.DefaultQueryAuthSchemeProvider;
+
+/**
+ * An auth scheme provider for Query service. The auth scheme provider takes a set of parameters using
+ * {@link QueryAuthSchemeParams}, and resolves a list of {@link AuthSchemeOption} based on the given parameters.
+ */
+@Generated("software.amazon.awssdk:codegen")
+@SdkPublicApi
+public interface QueryAuthSchemeProvider extends AuthSchemeProvider {
+ /**
+ * Resolve the auth schemes based on the given set of parameters.
+ */
+ List resolveAuthScheme(QueryAuthSchemeParams authSchemeParams);
+
+ /**
+ * Resolve the auth schemes based on the given set of parameters.
+ */
+ default List resolveAuthScheme(Consumer consumer) {
+ QueryAuthSchemeParams.Builder builder = QueryAuthSchemeParams.builder();
+ consumer.accept(builder);
+ return resolveAuthScheme(builder.build());
+ }
+
+ /**
+ * Get the default auth scheme provider.
+ */
+ static QueryAuthSchemeProvider defaultProvider() {
+ return DefaultQueryAuthSchemeProvider.create();
+ }
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/auth-with-legacy-trait-auth-scheme-default-provider.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/auth-with-legacy-trait-auth-scheme-default-provider.java
new file mode 100644
index 000000000000..1547ed4f412b
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/auth-with-legacy-trait-auth-scheme-default-provider.java
@@ -0,0 +1,57 @@
+/*
+ * 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.services.authwithlegacytrait.auth.scheme.internal;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import software.amazon.awssdk.annotations.Generated;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.http.auth.aws.signer.AwsV4HttpSigner;
+import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption;
+import software.amazon.awssdk.services.authwithlegacytrait.auth.scheme.AuthWithLegacyTraitAuthSchemeParams;
+import software.amazon.awssdk.services.authwithlegacytrait.auth.scheme.AuthWithLegacyTraitAuthSchemeProvider;
+
+@Generated("software.amazon.awssdk:codegen")
+@SdkInternalApi
+public final class DefaultAuthWithLegacyTraitAuthSchemeProvider implements AuthWithLegacyTraitAuthSchemeProvider {
+ private static final DefaultAuthWithLegacyTraitAuthSchemeProvider DEFAULT = new DefaultAuthWithLegacyTraitAuthSchemeProvider();
+
+ private DefaultAuthWithLegacyTraitAuthSchemeProvider() {
+ }
+
+ public static DefaultAuthWithLegacyTraitAuthSchemeProvider create() {
+ return DEFAULT;
+ }
+
+ @Override
+ public List resolveAuthScheme(AuthWithLegacyTraitAuthSchemeParams params) {
+ List options = new ArrayList<>();
+ switch (params.operation()) {
+ case "OperationWithBearerAuth":
+ options.add(AuthSchemeOption.builder().schemeId("smithy.api#httpBearerAuth").build());
+ break;
+ case "OperationWithNoAuth":
+ options.add(AuthSchemeOption.builder().schemeId("smithy.api#noAuth").build());
+ break;
+ default:
+ options.add(AuthSchemeOption.builder().schemeId("aws.auth#sigv4")
+ .putSignerProperty(AwsV4HttpSigner.SERVICE_SIGNING_NAME, "authwithlegacytraitservice")
+ .putSignerProperty(AwsV4HttpSigner.REGION_NAME, params.region().id()).build());
+ break;
+ }
+ return Collections.unmodifiableList(options);
+ }
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/default-auth-scheme-params.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/default-auth-scheme-params.java
new file mode 100644
index 000000000000..d6ae018038a8
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/default-auth-scheme-params.java
@@ -0,0 +1,70 @@
+/*
+ * 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.services.query.auth.scheme.internal;
+
+import java.util.Optional;
+import software.amazon.awssdk.annotations.Generated;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.services.query.auth.scheme.QueryAuthSchemeParams;
+import software.amazon.awssdk.utils.Validate;
+
+@Generated("software.amazon.awssdk:codegen")
+@SdkInternalApi
+public final class DefaultQueryAuthSchemeParams implements QueryAuthSchemeParams {
+ private final String operation;
+ private final String region;
+
+ private DefaultQueryAuthSchemeParams(Builder builder) {
+ this.operation = Validate.paramNotNull(builder.operation, "operation");
+ this.region = builder.region;
+ }
+
+ public static QueryAuthSchemeParams.Builder builder() {
+ return new Builder();
+ }
+
+ @Override
+ public String operation() {
+ return operation;
+ }
+
+ @Override
+ public Optional region() {
+ return region == null ? Optional.empty() : Optional.of(region);
+ }
+
+ private static final class Builder implements QueryAuthSchemeParams.Builder {
+ private String operation;
+ private String region;
+
+ @Override
+ public Builder operation(String operation) {
+ this.operation = operation;
+ return this;
+ }
+
+ @Override
+ public Builder region(String region) {
+ this.region = region;
+ return this;
+ }
+
+ @Override
+ public QueryAuthSchemeParams build() {
+ return new DefaultQueryAuthSchemeParams(this);
+ }
+ }
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/default-auth-scheme-provider.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/default-auth-scheme-provider.java
new file mode 100644
index 000000000000..d1e365854ac3
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/default-auth-scheme-provider.java
@@ -0,0 +1,43 @@
+/*
+ * 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.services.query.auth.scheme.internal;
+
+import java.util.ArrayList;
+import java.util.List;
+import software.amazon.awssdk.annotations.Generated;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption;
+import software.amazon.awssdk.services.query.auth.scheme.QueryAuthSchemeParams;
+import software.amazon.awssdk.services.query.auth.scheme.QueryAuthSchemeProvider;
+
+@Generated("software.amazon.awssdk:codegen")
+@SdkInternalApi
+public final class DefaultQueryAuthSchemeProvider implements QueryAuthSchemeProvider {
+
+ private static final DefaultQueryAuthSchemeProvider DEFAULT = new DefaultQueryAuthSchemeProvider();
+
+ private DefaultQueryAuthSchemeProvider() {
+ }
+
+ public static DefaultQueryAuthSchemeProvider create() {
+ return DEFAULT;
+ }
+
+ @Override
+ public List resolveAuthScheme(QueryAuthSchemeParams authSchemeParams) {
+ return new ArrayList<>();
+ }
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/granular-auth-scheme-default-provider.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/granular-auth-scheme-default-provider.java
new file mode 100644
index 000000000000..33c084fbc7d1
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/granular-auth-scheme-default-provider.java
@@ -0,0 +1,74 @@
+/*
+ * 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.services.database.auth.scheme.internal;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import software.amazon.awssdk.annotations.Generated;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.http.auth.aws.signer.AwsV4HttpSigner;
+import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption;
+import software.amazon.awssdk.services.database.auth.scheme.DatabaseAuthSchemeParams;
+import software.amazon.awssdk.services.database.auth.scheme.DatabaseAuthSchemeProvider;
+
+@Generated("software.amazon.awssdk:codegen")
+@SdkInternalApi
+public final class DefaultDatabaseAuthSchemeProvider implements DatabaseAuthSchemeProvider {
+ private static final DefaultDatabaseAuthSchemeProvider DEFAULT = new DefaultDatabaseAuthSchemeProvider();
+
+ private DefaultDatabaseAuthSchemeProvider() {
+ }
+
+ public static DefaultDatabaseAuthSchemeProvider create() {
+ return DEFAULT;
+ }
+
+ @Override
+ public List resolveAuthScheme(DatabaseAuthSchemeParams params) {
+ List options = new ArrayList<>();
+ switch (params.operation()) {
+ case "GetRow":
+ case "GetRowV2":
+ options.add(AuthSchemeOption.builder().schemeId("aws.auth#sigv4")
+ .putSignerProperty(AwsV4HttpSigner.SERVICE_SIGNING_NAME, "database-service")
+ .putSignerProperty(AwsV4HttpSigner.REGION_NAME, params.region().id()).build());
+ options.add(AuthSchemeOption.builder().schemeId("smithy.api#httpBearerAuth").build());
+ break;
+ case "ListRows":
+ options.add(AuthSchemeOption.builder().schemeId("smithy.api#httpBearerAuth").build());
+ break;
+ case "PutRow":
+ options.add(AuthSchemeOption.builder().schemeId("aws.auth#sigv4")
+ .putSignerProperty(AwsV4HttpSigner.SERVICE_SIGNING_NAME, "database-service")
+ .putSignerProperty(AwsV4HttpSigner.REGION_NAME, params.region().id()).build());
+ break;
+ case "WriteRowResponse":
+ options.add(AuthSchemeOption.builder().schemeId("aws.auth#sigv4")
+ .putSignerProperty(AwsV4HttpSigner.SERVICE_SIGNING_NAME, "database-service")
+ .putSignerProperty(AwsV4HttpSigner.REGION_NAME, params.region().id())
+ .putSignerProperty(AwsV4HttpSigner.PAYLOAD_SIGNING_ENABLED, false).build());
+ break;
+ default:
+ options.add(AuthSchemeOption.builder().schemeId("smithy.api#httpBearerAuth").build());
+ options.add(AuthSchemeOption.builder().schemeId("aws.auth#sigv4")
+ .putSignerProperty(AwsV4HttpSigner.SERVICE_SIGNING_NAME, "database-service")
+ .putSignerProperty(AwsV4HttpSigner.REGION_NAME, params.region().id()).build());
+ break;
+ }
+ return Collections.unmodifiableList(options);
+ }
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/mini-s3-auth-scheme-default-provider.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/mini-s3-auth-scheme-default-provider.java
new file mode 100644
index 000000000000..dd7224fd84c7
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/mini-s3-auth-scheme-default-provider.java
@@ -0,0 +1,50 @@
+/*
+ * 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.services.minis3.auth.scheme.internal;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import software.amazon.awssdk.annotations.Generated;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.http.auth.aws.signer.AwsV4HttpSigner;
+import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption;
+import software.amazon.awssdk.services.minis3.auth.scheme.MiniS3AuthSchemeParams;
+import software.amazon.awssdk.services.minis3.auth.scheme.MiniS3AuthSchemeProvider;
+
+@Generated("software.amazon.awssdk:codegen")
+@SdkInternalApi
+public final class DefaultMiniS3AuthSchemeProvider implements MiniS3AuthSchemeProvider {
+ private static final DefaultMiniS3AuthSchemeProvider DEFAULT = new DefaultMiniS3AuthSchemeProvider();
+
+ private DefaultMiniS3AuthSchemeProvider() {
+ }
+
+ public static DefaultMiniS3AuthSchemeProvider create() {
+ return DEFAULT;
+ }
+
+ @Override
+ public List resolveAuthScheme(MiniS3AuthSchemeParams params) {
+ List options = new ArrayList<>();
+ options.add(AuthSchemeOption.builder().schemeId("aws.auth#sigv4")
+ .putSignerProperty(AwsV4HttpSigner.SERVICE_SIGNING_NAME, "mini-s3-service")
+ .putSignerProperty(AwsV4HttpSigner.REGION_NAME, params.region().id())
+ .putSignerProperty(AwsV4HttpSigner.DOUBLE_URL_ENCODE, false)
+ .putSignerProperty(AwsV4HttpSigner.NORMALIZE_PATH, false)
+ .putSignerProperty(AwsV4HttpSigner.PAYLOAD_SIGNING_ENABLED, false).build());
+ return Collections.unmodifiableList(options);
+ }
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/ops-with-no-auth-auth-scheme-default-provider.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/ops-with-no-auth-auth-scheme-default-provider.java
new file mode 100644
index 000000000000..7a3553a47e59
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/ops-with-no-auth-auth-scheme-default-provider.java
@@ -0,0 +1,63 @@
+/*
+ * 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.services.database.auth.scheme.internal;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import software.amazon.awssdk.annotations.Generated;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.http.auth.aws.signer.AwsV4HttpSigner;
+import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption;
+import software.amazon.awssdk.services.database.auth.scheme.DatabaseAuthSchemeParams;
+import software.amazon.awssdk.services.database.auth.scheme.DatabaseAuthSchemeProvider;
+
+@Generated("software.amazon.awssdk:codegen")
+@SdkInternalApi
+public final class DefaultDatabaseAuthSchemeProvider implements DatabaseAuthSchemeProvider {
+ private static final DefaultDatabaseAuthSchemeProvider DEFAULT = new DefaultDatabaseAuthSchemeProvider();
+
+ private DefaultDatabaseAuthSchemeProvider() {
+ }
+
+ public static DefaultDatabaseAuthSchemeProvider create() {
+ return DEFAULT;
+ }
+
+ @Override
+ public List resolveAuthScheme(DatabaseAuthSchemeParams params) {
+ List options = new ArrayList<>();
+ switch (params.operation()) {
+ case "GetDatabaseVersion":
+ options.add(AuthSchemeOption.builder().schemeId("smithy.api#noAuth").build());
+ break;
+ case "GetRow":
+ options.add(AuthSchemeOption.builder().schemeId("aws.auth#sigv4")
+ .putSignerProperty(AwsV4HttpSigner.SERVICE_SIGNING_NAME, "database-service")
+ .putSignerProperty(AwsV4HttpSigner.REGION_NAME, params.region().id()).build());
+ options.add(AuthSchemeOption.builder().schemeId("smithy.api#httpBearerAuth").build());
+ options.add(AuthSchemeOption.builder().schemeId("smithy.api#noAuth").build());
+ break;
+ default:
+ options.add(AuthSchemeOption.builder().schemeId("aws.auth#sigv4")
+ .putSignerProperty(AwsV4HttpSigner.SERVICE_SIGNING_NAME, "database-service")
+ .putSignerProperty(AwsV4HttpSigner.REGION_NAME, params.region().id()).build());
+ options.add(AuthSchemeOption.builder().schemeId("smithy.api#httpBearerAuth").build());
+ break;
+ }
+ return Collections.unmodifiableList(options);
+ }
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-auth-scheme-default-params.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-auth-scheme-default-params.java
new file mode 100644
index 000000000000..8d4589400e62
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-auth-scheme-default-params.java
@@ -0,0 +1,85 @@
+/*
+ * 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.services.query.auth.scheme.internal;
+
+import software.amazon.awssdk.annotations.Generated;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.query.auth.scheme.QueryAuthSchemeParams;
+import software.amazon.awssdk.utils.Validate;
+
+@Generated("software.amazon.awssdk:codegen")
+@SdkInternalApi
+public final class DefaultQueryAuthSchemeParams implements QueryAuthSchemeParams {
+ private final String operation;
+
+ private final Region region;
+
+ private DefaultQueryAuthSchemeParams(Builder builder) {
+ this.operation = Validate.paramNotNull(builder.operation, "operation");
+ this.region = builder.region;
+ }
+
+ public static QueryAuthSchemeParams.Builder builder() {
+ return new Builder();
+ }
+
+ @Override
+ public String operation() {
+ return operation;
+ }
+
+ @Override
+ public Region region() {
+ return region;
+ }
+
+ @Override
+ public QueryAuthSchemeParams.Builder toBuilder() {
+ return new Builder(this);
+ }
+
+ private static final class Builder implements QueryAuthSchemeParams.Builder {
+ private String operation;
+
+ private Region region;
+
+ Builder() {
+ }
+
+ Builder(DefaultQueryAuthSchemeParams params) {
+ this.operation = params.operation;
+ this.region = params.region;
+ }
+
+ @Override
+ public Builder operation(String operation) {
+ this.operation = operation;
+ return this;
+ }
+
+ @Override
+ public Builder region(Region region) {
+ this.region = region;
+ return this;
+ }
+
+ @Override
+ public QueryAuthSchemeParams build() {
+ return new DefaultQueryAuthSchemeParams(this);
+ }
+ }
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-auth-scheme-default-provider.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-auth-scheme-default-provider.java
new file mode 100644
index 000000000000..5d51e68ebb1e
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-auth-scheme-default-provider.java
@@ -0,0 +1,58 @@
+/*
+ * 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.services.query.auth.scheme.internal;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import software.amazon.awssdk.annotations.Generated;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.http.auth.aws.signer.AwsV4HttpSigner;
+import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption;
+import software.amazon.awssdk.services.query.auth.scheme.QueryAuthSchemeParams;
+import software.amazon.awssdk.services.query.auth.scheme.QueryAuthSchemeProvider;
+
+@Generated("software.amazon.awssdk:codegen")
+@SdkInternalApi
+public final class DefaultQueryAuthSchemeProvider implements QueryAuthSchemeProvider {
+ private static final DefaultQueryAuthSchemeProvider DEFAULT = new DefaultQueryAuthSchemeProvider();
+
+ private DefaultQueryAuthSchemeProvider() {
+ }
+
+ public static DefaultQueryAuthSchemeProvider create() {
+ return DEFAULT;
+ }
+
+ @Override
+ public List resolveAuthScheme(QueryAuthSchemeParams params) {
+ List options = new ArrayList<>();
+ switch (params.operation()) {
+ case "BearerAuthOperation":
+ options.add(AuthSchemeOption.builder().schemeId("smithy.api#httpBearerAuth").build());
+ break;
+ case "OperationWithNoneAuthType":
+ options.add(AuthSchemeOption.builder().schemeId("smithy.api#noAuth").build());
+ break;
+ default:
+ options.add(AuthSchemeOption.builder().schemeId("aws.auth#sigv4")
+ .putSignerProperty(AwsV4HttpSigner.SERVICE_SIGNING_NAME, "query-service")
+ .putSignerProperty(AwsV4HttpSigner.REGION_NAME, params.region().id()).build());
+ break;
+ }
+ return Collections.unmodifiableList(options);
+ }
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-auth-scheme-interceptor.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-auth-scheme-interceptor.java
new file mode 100644
index 000000000000..7c59b1f5af74
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-auth-scheme-interceptor.java
@@ -0,0 +1,128 @@
+package software.amazon.awssdk.services.query.auth.scheme.internal;
+
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+import software.amazon.awssdk.annotations.Generated;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.awscore.AwsExecutionAttribute;
+import software.amazon.awssdk.core.SdkRequest;
+import software.amazon.awssdk.core.SelectedAuthScheme;
+import software.amazon.awssdk.core.exception.SdkException;
+import software.amazon.awssdk.core.interceptor.Context;
+import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
+import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
+import software.amazon.awssdk.core.interceptor.SdkExecutionAttribute;
+import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute;
+import software.amazon.awssdk.core.internal.util.MetricUtils;
+import software.amazon.awssdk.core.metrics.CoreMetric;
+import software.amazon.awssdk.http.auth.spi.scheme.AuthScheme;
+import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption;
+import software.amazon.awssdk.identity.spi.AwsCredentialsIdentity;
+import software.amazon.awssdk.identity.spi.Identity;
+import software.amazon.awssdk.identity.spi.IdentityProvider;
+import software.amazon.awssdk.identity.spi.IdentityProviders;
+import software.amazon.awssdk.identity.spi.ResolveIdentityRequest;
+import software.amazon.awssdk.identity.spi.TokenIdentity;
+import software.amazon.awssdk.metrics.MetricCollector;
+import software.amazon.awssdk.metrics.SdkMetric;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.query.auth.scheme.QueryAuthSchemeParams;
+import software.amazon.awssdk.services.query.auth.scheme.QueryAuthSchemeProvider;
+import software.amazon.awssdk.services.query.endpoints.internal.AuthSchemeUtils;
+import software.amazon.awssdk.utils.Logger;
+import software.amazon.awssdk.utils.Validate;
+
+@Generated("software.amazon.awssdk:codegen")
+@SdkInternalApi
+public final class QueryAuthSchemeInterceptor implements ExecutionInterceptor {
+ private static Logger LOG = Logger.loggerFor(QueryAuthSchemeInterceptor.class);
+
+ @Override
+ public void beforeExecution(Context.BeforeExecution context, ExecutionAttributes executionAttributes) {
+ List authOptions = resolveAuthOptions(context, executionAttributes);
+ SelectedAuthScheme extends Identity> selectedAuthScheme = selectAuthScheme(authOptions, executionAttributes);
+ AuthSchemeUtils.putSelectedAuthScheme(executionAttributes, selectedAuthScheme);
+ }
+
+ private List resolveAuthOptions(Context.BeforeExecution context, ExecutionAttributes executionAttributes) {
+ QueryAuthSchemeProvider authSchemeProvider = Validate.isInstanceOf(QueryAuthSchemeProvider.class,
+ executionAttributes.getAttribute(SdkInternalExecutionAttribute.AUTH_SCHEME_RESOLVER),
+ "Expected an instance of QueryAuthSchemeProvider");
+ QueryAuthSchemeParams params = authSchemeParams(context.request(), executionAttributes);
+ return authSchemeProvider.resolveAuthScheme(params);
+ }
+
+ private SelectedAuthScheme extends Identity> selectAuthScheme(List authOptions,
+ ExecutionAttributes executionAttributes) {
+ MetricCollector metricCollector = executionAttributes.getAttribute(SdkExecutionAttribute.API_CALL_METRIC_COLLECTOR);
+ Map> authSchemes = executionAttributes.getAttribute(SdkInternalExecutionAttribute.AUTH_SCHEMES);
+ IdentityProviders identityProviders = executionAttributes
+ .getAttribute(SdkInternalExecutionAttribute.IDENTITY_PROVIDERS);
+ List> discardedReasons = new ArrayList<>();
+ for (AuthSchemeOption authOption : authOptions) {
+ AuthScheme> authScheme = authSchemes.get(authOption.schemeId());
+ SelectedAuthScheme extends Identity> selectedAuthScheme = trySelectAuthScheme(authOption, authScheme,
+ identityProviders, discardedReasons, metricCollector);
+ if (selectedAuthScheme != null) {
+ if (!discardedReasons.isEmpty()) {
+ LOG.debug(() -> String.format("%s auth will be used, discarded: '%s'", authOption.schemeId(),
+ discardedReasons.stream().map(Supplier::get).collect(Collectors.joining(", "))));
+ }
+ return selectedAuthScheme;
+ }
+ }
+ throw SdkException
+ .builder()
+ .message(
+ "Failed to determine how to authenticate the user: "
+ + discardedReasons.stream().map(Supplier::get).collect(Collectors.joining(", "))).build();
+ }
+
+ private QueryAuthSchemeParams authSchemeParams(SdkRequest request, ExecutionAttributes executionAttributes) {
+ String operation = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME);
+ Region region = executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION);
+ return QueryAuthSchemeParams.builder().operation(operation).region(region).build();
+ }
+
+ private SelectedAuthScheme trySelectAuthScheme(AuthSchemeOption authOption, AuthScheme authScheme,
+ IdentityProviders identityProviders, List> discardedReasons,
+ MetricCollector metricCollector) {
+ if (authScheme == null) {
+ discardedReasons.add(() -> String.format("'%s' is not enabled for this request.", authOption.schemeId()));
+ return null;
+ }
+ IdentityProvider identityProvider = authScheme.identityProvider(identityProviders);
+ if (identityProvider == null) {
+ discardedReasons
+ .add(() -> String.format("'%s' does not have an identity provider configured.", authOption.schemeId()));
+ return null;
+ }
+ ResolveIdentityRequest.Builder identityRequestBuilder = ResolveIdentityRequest.builder();
+ authOption.forEachIdentityProperty(identityRequestBuilder::putProperty);
+ CompletableFuture extends T> identity;
+ SdkMetric metric = getIdentityMetric(identityProvider);
+ if (metric == null) {
+ identity = identityProvider.resolveIdentity(identityRequestBuilder.build());
+ } else {
+ identity = MetricUtils.reportDuration(() -> identityProvider.resolveIdentity(identityRequestBuilder.build()),
+ metricCollector, metric);
+ }
+ return new SelectedAuthScheme<>(identity, authScheme.signer(), authOption);
+ }
+
+ private SdkMetric getIdentityMetric(IdentityProvider> identityProvider) {
+ Class> identityType = identityProvider.identityType();
+ if (identityType == AwsCredentialsIdentity.class) {
+ return CoreMetric.CREDENTIALS_FETCH_DURATION;
+ }
+ if (identityType == TokenIdentity.class) {
+ return CoreMetric.TOKEN_FETCH_DURATION;
+ }
+ return null;
+ }
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-auth-scheme-params.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-auth-scheme-params.java
new file mode 100644
index 000000000000..b726c4a81e09
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-auth-scheme-params.java
@@ -0,0 +1,73 @@
+/*
+ * 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.services.query.auth.scheme;
+
+import software.amazon.awssdk.annotations.Generated;
+import software.amazon.awssdk.annotations.SdkPublicApi;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.query.auth.scheme.internal.DefaultQueryAuthSchemeParams;
+import software.amazon.awssdk.utils.builder.CopyableBuilder;
+import software.amazon.awssdk.utils.builder.ToCopyableBuilder;
+
+/**
+ * The parameters object used to resolve the auth schemes for the Query service.
+ */
+@Generated("software.amazon.awssdk:codegen")
+@SdkPublicApi
+public interface QueryAuthSchemeParams extends ToCopyableBuilder {
+ /**
+ * Get a new builder for creating a {@link QueryAuthSchemeParams}.
+ */
+ static Builder builder() {
+ return DefaultQueryAuthSchemeParams.builder();
+ }
+
+ /**
+ * Returns the operation for which to resolve the auth scheme.
+ */
+ String operation();
+
+ /**
+ * Returns the region. The region parameter may be used with the "aws.auth#sigv4" auth scheme.
+ */
+ Region region();
+
+ /**
+ * Returns a {@link Builder} to customize the parameters.
+ */
+ Builder toBuilder();
+
+ /**
+ * A builder for a {@link QueryAuthSchemeParams}.
+ */
+ interface Builder extends CopyableBuilder {
+ /**
+ * Set the operation for which to resolve the auth scheme.
+ */
+ Builder operation(String operation);
+
+ /**
+ * Set the region. The region parameter may be used with the "aws.auth#sigv4" auth scheme.
+ */
+ Builder region(Region region);
+
+ /**
+ * Returns a {@link QueryAuthSchemeParams} object that is created from the properties that have been set on the
+ * builder.
+ */
+ QueryAuthSchemeParams build();
+ }
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-auth-scheme-provider.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-auth-scheme-provider.java
new file mode 100644
index 000000000000..a4f84dc2665a
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-auth-scheme-provider.java
@@ -0,0 +1,53 @@
+/*
+ * 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.services.query.auth.scheme;
+
+import java.util.List;
+import java.util.function.Consumer;
+import software.amazon.awssdk.annotations.Generated;
+import software.amazon.awssdk.annotations.SdkPublicApi;
+import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption;
+import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeProvider;
+import software.amazon.awssdk.services.query.auth.scheme.internal.DefaultQueryAuthSchemeProvider;
+
+/**
+ * An auth scheme provider for Query service. The auth scheme provider takes a set of parameters using
+ * {@link QueryAuthSchemeParams}, and resolves a list of {@link AuthSchemeOption} based on the given parameters.
+ */
+@Generated("software.amazon.awssdk:codegen")
+@SdkPublicApi
+public interface QueryAuthSchemeProvider extends AuthSchemeProvider {
+ /**
+ * Resolve the auth schemes based on the given set of parameters.
+ */
+ List resolveAuthScheme(QueryAuthSchemeParams authSchemeParams);
+
+ /**
+ * Resolve the auth schemes based on the given set of parameters.
+ */
+ default List resolveAuthScheme(Consumer consumer) {
+ QueryAuthSchemeParams.Builder builder = QueryAuthSchemeParams.builder();
+ consumer.accept(builder);
+ return resolveAuthScheme(builder.build());
+ }
+
+ /**
+ * Get the default auth scheme provider.
+ */
+ static QueryAuthSchemeProvider defaultProvider() {
+ return DefaultQueryAuthSchemeProvider.create();
+ }
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-default-params-with-allowlist.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-default-params-with-allowlist.java
new file mode 100644
index 000000000000..e9fb9b7cfaeb
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-default-params-with-allowlist.java
@@ -0,0 +1,195 @@
+/*
+ * 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.services.query.auth.scheme.internal;
+
+import software.amazon.awssdk.annotations.Generated;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.query.auth.scheme.QueryAuthSchemeParams;
+import software.amazon.awssdk.utils.Validate;
+
+@Generated("software.amazon.awssdk:codegen")
+@SdkInternalApi
+public final class DefaultQueryAuthSchemeParams implements QueryAuthSchemeParams {
+ private final String operation;
+
+ private final Region region;
+
+ private final Boolean defaultTrueParam;
+
+ private final String defaultStringParam;
+
+ private final String deprecatedParam;
+
+ private final Boolean booleanContextParam;
+
+ private final String stringContextParam;
+
+ private final String operationContextParam;
+
+ private DefaultQueryAuthSchemeParams(Builder builder) {
+ this.operation = Validate.paramNotNull(builder.operation, "operation");
+ this.region = builder.region;
+ this.defaultTrueParam = Validate.paramNotNull(builder.defaultTrueParam, "defaultTrueParam");
+ this.defaultStringParam = Validate.paramNotNull(builder.defaultStringParam, "defaultStringParam");
+ this.deprecatedParam = builder.deprecatedParam;
+ this.booleanContextParam = builder.booleanContextParam;
+ this.stringContextParam = builder.stringContextParam;
+ this.operationContextParam = builder.operationContextParam;
+ }
+
+ public static QueryAuthSchemeParams.Builder builder() {
+ return new Builder();
+ }
+
+ @Override
+ public String operation() {
+ return operation;
+ }
+
+ @Override
+ public Region region() {
+ return region;
+ }
+
+ @Override
+ public Boolean defaultTrueParam() {
+ return defaultTrueParam;
+ }
+
+ @Override
+ public String defaultStringParam() {
+ return defaultStringParam;
+ }
+
+ @Deprecated
+ @Override
+ public String deprecatedParam() {
+ return deprecatedParam;
+ }
+
+ @Override
+ public Boolean booleanContextParam() {
+ return booleanContextParam;
+ }
+
+ @Override
+ public String stringContextParam() {
+ return stringContextParam;
+ }
+
+ @Override
+ public String operationContextParam() {
+ return operationContextParam;
+ }
+
+ @Override
+ public QueryAuthSchemeParams.Builder toBuilder() {
+ return new Builder(this);
+ }
+
+ private static final class Builder implements QueryAuthSchemeParams.Builder {
+ private String operation;
+
+ private Region region;
+
+ private Boolean defaultTrueParam = true;
+
+ private String defaultStringParam = "hello endpoints";
+
+ private String deprecatedParam;
+
+ private Boolean booleanContextParam;
+
+ private String stringContextParam;
+
+ private String operationContextParam;
+
+ Builder() {
+ }
+
+ Builder(DefaultQueryAuthSchemeParams params) {
+ this.operation = params.operation;
+ this.region = params.region;
+ this.defaultTrueParam = params.defaultTrueParam;
+ this.defaultStringParam = params.defaultStringParam;
+ this.deprecatedParam = params.deprecatedParam;
+ this.booleanContextParam = params.booleanContextParam;
+ this.stringContextParam = params.stringContextParam;
+ this.operationContextParam = params.operationContextParam;
+ }
+
+ @Override
+ public Builder operation(String operation) {
+ this.operation = operation;
+ return this;
+ }
+
+ @Override
+ public Builder region(Region region) {
+ this.region = region;
+ return this;
+ }
+
+ @Override
+ public Builder defaultTrueParam(Boolean defaultTrueParam) {
+ this.defaultTrueParam = defaultTrueParam;
+ if (this.defaultTrueParam == null) {
+ this.defaultTrueParam = true;
+ }
+ return this;
+ }
+
+ @Override
+ public Builder defaultStringParam(String defaultStringParam) {
+ this.defaultStringParam = defaultStringParam;
+ if (this.defaultStringParam == null) {
+ this.defaultStringParam = "hello endpoints";
+ }
+ return this;
+ }
+
+ @Deprecated
+ @Override
+ public Builder deprecatedParam(String deprecatedParam) {
+ this.deprecatedParam = deprecatedParam;
+ return this;
+ }
+
+ @Override
+ public Builder booleanContextParam(Boolean booleanContextParam) {
+ this.booleanContextParam = booleanContextParam;
+ return this;
+ }
+
+ @Override
+ public Builder stringContextParam(String stringContextParam) {
+ this.stringContextParam = stringContextParam;
+ return this;
+ }
+
+ @Override
+ public Builder operationContextParam(String operationContextParam) {
+ this.operationContextParam = operationContextParam;
+ return this;
+ }
+
+ @Override
+ public QueryAuthSchemeParams build() {
+ return new DefaultQueryAuthSchemeParams(this);
+ }
+ }
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-default-params-without-allowlist.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-default-params-without-allowlist.java
new file mode 100644
index 000000000000..fc20bf433c72
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-default-params-without-allowlist.java
@@ -0,0 +1,246 @@
+/*
+ * 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.services.query.auth.scheme.internal;
+
+import software.amazon.awssdk.annotations.Generated;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.query.auth.scheme.QueryAuthSchemeParams;
+import software.amazon.awssdk.utils.Validate;
+
+@Generated("software.amazon.awssdk:codegen")
+@SdkInternalApi
+public final class DefaultQueryAuthSchemeParams implements QueryAuthSchemeParams {
+ private final String operation;
+
+ private final Region region;
+
+ private final Boolean useDualStackEndpoint;
+
+ private final Boolean useFIPSEndpoint;
+
+ private final String endpointId;
+
+ private final Boolean defaultTrueParam;
+
+ private final String defaultStringParam;
+
+ private final String deprecatedParam;
+
+ private final Boolean booleanContextParam;
+
+ private final String stringContextParam;
+
+ private final String operationContextParam;
+
+ private DefaultQueryAuthSchemeParams(Builder builder) {
+ this.operation = Validate.paramNotNull(builder.operation, "operation");
+ this.region = builder.region;
+ this.useDualStackEndpoint = builder.useDualStackEndpoint;
+ this.useFIPSEndpoint = builder.useFIPSEndpoint;
+ this.endpointId = builder.endpointId;
+ this.defaultTrueParam = Validate.paramNotNull(builder.defaultTrueParam, "defaultTrueParam");
+ this.defaultStringParam = Validate.paramNotNull(builder.defaultStringParam, "defaultStringParam");
+ this.deprecatedParam = builder.deprecatedParam;
+ this.booleanContextParam = builder.booleanContextParam;
+ this.stringContextParam = builder.stringContextParam;
+ this.operationContextParam = builder.operationContextParam;
+ }
+
+ public static QueryAuthSchemeParams.Builder builder() {
+ return new Builder();
+ }
+
+ @Override
+ public String operation() {
+ return operation;
+ }
+
+ @Override
+ public Region region() {
+ return region;
+ }
+
+ @Override
+ public Boolean useDualStackEndpoint() {
+ return useDualStackEndpoint;
+ }
+
+ @Override
+ public Boolean useFipsEndpoint() {
+ return useFIPSEndpoint;
+ }
+
+ @Override
+ public String endpointId() {
+ return endpointId;
+ }
+
+ @Override
+ public Boolean defaultTrueParam() {
+ return defaultTrueParam;
+ }
+
+ @Override
+ public String defaultStringParam() {
+ return defaultStringParam;
+ }
+
+ @Deprecated
+ @Override
+ public String deprecatedParam() {
+ return deprecatedParam;
+ }
+
+ @Override
+ public Boolean booleanContextParam() {
+ return booleanContextParam;
+ }
+
+ @Override
+ public String stringContextParam() {
+ return stringContextParam;
+ }
+
+ @Override
+ public String operationContextParam() {
+ return operationContextParam;
+ }
+
+ @Override
+ public QueryAuthSchemeParams.Builder toBuilder() {
+ return new Builder(this);
+ }
+
+ private static final class Builder implements QueryAuthSchemeParams.Builder {
+ private String operation;
+
+ private Region region;
+
+ private Boolean useDualStackEndpoint;
+
+ private Boolean useFIPSEndpoint;
+
+ private String endpointId;
+
+ private Boolean defaultTrueParam = true;
+
+ private String defaultStringParam = "hello endpoints";
+
+ private String deprecatedParam;
+
+ private Boolean booleanContextParam;
+
+ private String stringContextParam;
+
+ private String operationContextParam;
+
+ Builder() {
+ }
+
+ Builder(DefaultQueryAuthSchemeParams params) {
+ this.operation = params.operation;
+ this.region = params.region;
+ this.useDualStackEndpoint = params.useDualStackEndpoint;
+ this.useFIPSEndpoint = params.useFIPSEndpoint;
+ this.endpointId = params.endpointId;
+ this.defaultTrueParam = params.defaultTrueParam;
+ this.defaultStringParam = params.defaultStringParam;
+ this.deprecatedParam = params.deprecatedParam;
+ this.booleanContextParam = params.booleanContextParam;
+ this.stringContextParam = params.stringContextParam;
+ this.operationContextParam = params.operationContextParam;
+ }
+
+ @Override
+ public Builder operation(String operation) {
+ this.operation = operation;
+ return this;
+ }
+
+ @Override
+ public Builder region(Region region) {
+ this.region = region;
+ return this;
+ }
+
+ @Override
+ public Builder useDualStackEndpoint(Boolean useDualStackEndpoint) {
+ this.useDualStackEndpoint = useDualStackEndpoint;
+ return this;
+ }
+
+ @Override
+ public Builder useFipsEndpoint(Boolean useFIPSEndpoint) {
+ this.useFIPSEndpoint = useFIPSEndpoint;
+ return this;
+ }
+
+ @Override
+ public Builder endpointId(String endpointId) {
+ this.endpointId = endpointId;
+ return this;
+ }
+
+ @Override
+ public Builder defaultTrueParam(Boolean defaultTrueParam) {
+ this.defaultTrueParam = defaultTrueParam;
+ if (this.defaultTrueParam == null) {
+ this.defaultTrueParam = true;
+ }
+ return this;
+ }
+
+ @Override
+ public Builder defaultStringParam(String defaultStringParam) {
+ this.defaultStringParam = defaultStringParam;
+ if (this.defaultStringParam == null) {
+ this.defaultStringParam = "hello endpoints";
+ }
+ return this;
+ }
+
+ @Deprecated
+ @Override
+ public Builder deprecatedParam(String deprecatedParam) {
+ this.deprecatedParam = deprecatedParam;
+ return this;
+ }
+
+ @Override
+ public Builder booleanContextParam(Boolean booleanContextParam) {
+ this.booleanContextParam = booleanContextParam;
+ return this;
+ }
+
+ @Override
+ public Builder stringContextParam(String stringContextParam) {
+ this.stringContextParam = stringContextParam;
+ return this;
+ }
+
+ @Override
+ public Builder operationContextParam(String operationContextParam) {
+ this.operationContextParam = operationContextParam;
+ return this;
+ }
+
+ @Override
+ public QueryAuthSchemeParams build() {
+ return new DefaultQueryAuthSchemeParams(this);
+ }
+ }
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-endpoint-provider-without-allowlist.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-endpoint-provider-without-allowlist.java
new file mode 100644
index 000000000000..d22e9c1ca151
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-endpoint-provider-without-allowlist.java
@@ -0,0 +1,82 @@
+package software.amazon.awssdk.services.query.auth.scheme.internal;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import software.amazon.awssdk.annotations.Generated;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute;
+import software.amazon.awssdk.awscore.endpoints.authscheme.EndpointAuthScheme;
+import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4AuthScheme;
+import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4aAuthScheme;
+import software.amazon.awssdk.endpoints.Endpoint;
+import software.amazon.awssdk.http.auth.aws.signer.AwsV4HttpSigner;
+import software.amazon.awssdk.http.auth.aws.signer.AwsV4aHttpSigner;
+import software.amazon.awssdk.http.auth.aws.signer.RegionSet;
+import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption;
+import software.amazon.awssdk.services.query.auth.scheme.QueryAuthSchemeParams;
+import software.amazon.awssdk.services.query.auth.scheme.QueryAuthSchemeProvider;
+import software.amazon.awssdk.services.query.endpoints.QueryEndpointParams;
+import software.amazon.awssdk.services.query.endpoints.QueryEndpointProvider;
+import software.amazon.awssdk.utils.CompletableFutureUtils;
+import software.amazon.awssdk.utils.Validate;
+
+@Generated("software.amazon.awssdk:codegen")
+@SdkInternalApi
+public final class DefaultQueryAuthSchemeProvider implements QueryAuthSchemeProvider {
+ private static final DefaultQueryAuthSchemeProvider DEFAULT = new DefaultQueryAuthSchemeProvider();
+
+ private static final QueryAuthSchemeProvider MODELED_RESOLVER = ModeledQueryAuthSchemeProvider.create();
+
+ private static final QueryEndpointProvider DELEGATE = QueryEndpointProvider.defaultProvider();
+
+ private DefaultQueryAuthSchemeProvider() {
+ }
+
+ public static QueryAuthSchemeProvider create() {
+ return DEFAULT;
+ }
+
+ @Override
+ public List resolveAuthScheme(QueryAuthSchemeParams params) {
+ QueryEndpointParams endpointParameters = QueryEndpointParams.builder().region(params.region())
+ .useDualStackEndpoint(params.useDualStackEndpoint()).useFipsEndpoint(params.useFipsEndpoint())
+ .endpointId(params.endpointId()).defaultTrueParam(params.defaultTrueParam())
+ .defaultStringParam(params.defaultStringParam()).deprecatedParam(params.deprecatedParam())
+ .booleanContextParam(params.booleanContextParam()).stringContextParam(params.stringContextParam())
+ .operationContextParam(params.operationContextParam()).build();
+ Endpoint endpoint = CompletableFutureUtils.joinLikeSync(DELEGATE.resolveEndpoint(endpointParameters));
+ List authSchemes = endpoint.attribute(AwsEndpointAttribute.AUTH_SCHEMES);
+ if (authSchemes == null) {
+ return MODELED_RESOLVER.resolveAuthScheme(params);
+ }
+ List options = new ArrayList<>();
+ for (EndpointAuthScheme authScheme : authSchemes) {
+ String name = authScheme.name();
+ switch (name) {
+ case "sigv4":
+ SigV4AuthScheme sigv4AuthScheme = Validate.isInstanceOf(SigV4AuthScheme.class, authScheme,
+ "Expecting auth scheme of class SigV4AuthScheme, got instead object of class %s", authScheme.getClass()
+ .getName());
+ options.add(AuthSchemeOption.builder().schemeId("aws.auth#sigv4")
+ .putSignerProperty(AwsV4HttpSigner.SERVICE_SIGNING_NAME, sigv4AuthScheme.signingName())
+ .putSignerProperty(AwsV4HttpSigner.REGION_NAME, sigv4AuthScheme.signingRegion())
+ .putSignerProperty(AwsV4HttpSigner.DOUBLE_URL_ENCODE, !sigv4AuthScheme.disableDoubleEncoding()).build());
+ break;
+ case "sigv4a":
+ SigV4aAuthScheme sigv4aAuthScheme = Validate.isInstanceOf(SigV4aAuthScheme.class, authScheme,
+ "Expecting auth scheme of class SigV4AuthScheme, got instead object of class %s", authScheme.getClass()
+ .getName());
+ RegionSet regionSet = RegionSet.create(sigv4aAuthScheme.signingRegionSet());
+ options.add(AuthSchemeOption.builder().schemeId("aws.auth#sigv4a")
+ .putSignerProperty(AwsV4aHttpSigner.SERVICE_SIGNING_NAME, sigv4aAuthScheme.signingName())
+ .putSignerProperty(AwsV4aHttpSigner.REGION_SET, regionSet)
+ .putSignerProperty(AwsV4aHttpSigner.DOUBLE_URL_ENCODE, !sigv4aAuthScheme.disableDoubleEncoding()).build());
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown auth scheme: " + name);
+ }
+ }
+ return Collections.unmodifiableList(options);
+ }
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-endpoint-provider.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-endpoint-provider.java
new file mode 100644
index 000000000000..0fd273b82882
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-endpoint-provider.java
@@ -0,0 +1,80 @@
+package software.amazon.awssdk.services.query.auth.scheme.internal;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import software.amazon.awssdk.annotations.Generated;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute;
+import software.amazon.awssdk.awscore.endpoints.authscheme.EndpointAuthScheme;
+import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4AuthScheme;
+import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4aAuthScheme;
+import software.amazon.awssdk.endpoints.Endpoint;
+import software.amazon.awssdk.http.auth.aws.signer.AwsV4HttpSigner;
+import software.amazon.awssdk.http.auth.aws.signer.AwsV4aHttpSigner;
+import software.amazon.awssdk.http.auth.aws.signer.RegionSet;
+import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption;
+import software.amazon.awssdk.services.query.auth.scheme.QueryAuthSchemeParams;
+import software.amazon.awssdk.services.query.auth.scheme.QueryAuthSchemeProvider;
+import software.amazon.awssdk.services.query.endpoints.QueryEndpointParams;
+import software.amazon.awssdk.services.query.endpoints.QueryEndpointProvider;
+import software.amazon.awssdk.utils.CompletableFutureUtils;
+import software.amazon.awssdk.utils.Validate;
+
+@Generated("software.amazon.awssdk:codegen")
+@SdkInternalApi
+public final class DefaultQueryAuthSchemeProvider implements QueryAuthSchemeProvider {
+ private static final DefaultQueryAuthSchemeProvider DEFAULT = new DefaultQueryAuthSchemeProvider();
+
+ private static final QueryAuthSchemeProvider MODELED_RESOLVER = ModeledQueryAuthSchemeProvider.create();
+
+ private static final QueryEndpointProvider DELEGATE = QueryEndpointProvider.defaultProvider();
+
+ private DefaultQueryAuthSchemeProvider() {
+ }
+
+ public static QueryAuthSchemeProvider create() {
+ return DEFAULT;
+ }
+
+ @Override
+ public List resolveAuthScheme(QueryAuthSchemeParams params) {
+ QueryEndpointParams endpointParameters = QueryEndpointParams.builder().region(params.region())
+ .defaultTrueParam(params.defaultTrueParam()).defaultStringParam(params.defaultStringParam())
+ .deprecatedParam(params.deprecatedParam()).booleanContextParam(params.booleanContextParam())
+ .stringContextParam(params.stringContextParam()).operationContextParam(params.operationContextParam()).build();
+ Endpoint endpoint = CompletableFutureUtils.joinLikeSync(DELEGATE.resolveEndpoint(endpointParameters));
+ List authSchemes = endpoint.attribute(AwsEndpointAttribute.AUTH_SCHEMES);
+ if (authSchemes == null) {
+ return MODELED_RESOLVER.resolveAuthScheme(params);
+ }
+ List options = new ArrayList<>();
+ for (EndpointAuthScheme authScheme : authSchemes) {
+ String name = authScheme.name();
+ switch (name) {
+ case "sigv4":
+ SigV4AuthScheme sigv4AuthScheme = Validate.isInstanceOf(SigV4AuthScheme.class, authScheme,
+ "Expecting auth scheme of class SigV4AuthScheme, got instead object of class %s", authScheme.getClass()
+ .getName());
+ options.add(AuthSchemeOption.builder().schemeId("aws.auth#sigv4")
+ .putSignerProperty(AwsV4HttpSigner.SERVICE_SIGNING_NAME, sigv4AuthScheme.signingName())
+ .putSignerProperty(AwsV4HttpSigner.REGION_NAME, sigv4AuthScheme.signingRegion())
+ .putSignerProperty(AwsV4HttpSigner.DOUBLE_URL_ENCODE, !sigv4AuthScheme.disableDoubleEncoding()).build());
+ break;
+ case "sigv4a":
+ SigV4aAuthScheme sigv4aAuthScheme = Validate.isInstanceOf(SigV4aAuthScheme.class, authScheme,
+ "Expecting auth scheme of class SigV4AuthScheme, got instead object of class %s", authScheme.getClass()
+ .getName());
+ RegionSet regionSet = RegionSet.create(sigv4aAuthScheme.signingRegionSet());
+ options.add(AuthSchemeOption.builder().schemeId("aws.auth#sigv4a")
+ .putSignerProperty(AwsV4aHttpSigner.SERVICE_SIGNING_NAME, sigv4aAuthScheme.signingName())
+ .putSignerProperty(AwsV4aHttpSigner.REGION_SET, regionSet)
+ .putSignerProperty(AwsV4aHttpSigner.DOUBLE_URL_ENCODE, !sigv4aAuthScheme.disableDoubleEncoding()).build());
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown auth scheme: " + name);
+ }
+ }
+ return Collections.unmodifiableList(options);
+ }
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-modeled-provider.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-modeled-provider.java
new file mode 100644
index 000000000000..f5bdc077f3b3
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-modeled-provider.java
@@ -0,0 +1,58 @@
+/*
+ * 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.services.query.auth.scheme.internal;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import software.amazon.awssdk.annotations.Generated;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.http.auth.aws.signer.AwsV4HttpSigner;
+import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption;
+import software.amazon.awssdk.services.query.auth.scheme.QueryAuthSchemeParams;
+import software.amazon.awssdk.services.query.auth.scheme.QueryAuthSchemeProvider;
+
+@Generated("software.amazon.awssdk:codegen")
+@SdkInternalApi
+public final class ModeledQueryAuthSchemeProvider implements QueryAuthSchemeProvider {
+ private static final ModeledQueryAuthSchemeProvider DEFAULT = new ModeledQueryAuthSchemeProvider();
+
+ private ModeledQueryAuthSchemeProvider() {
+ }
+
+ public static ModeledQueryAuthSchemeProvider create() {
+ return DEFAULT;
+ }
+
+ @Override
+ public List resolveAuthScheme(QueryAuthSchemeParams params) {
+ List options = new ArrayList<>();
+ switch (params.operation()) {
+ case "BearerAuthOperation":
+ options.add(AuthSchemeOption.builder().schemeId("smithy.api#httpBearerAuth").build());
+ break;
+ case "OperationWithNoneAuthType":
+ options.add(AuthSchemeOption.builder().schemeId("smithy.api#noAuth").build());
+ break;
+ default:
+ options.add(AuthSchemeOption.builder().schemeId("aws.auth#sigv4")
+ .putSignerProperty(AwsV4HttpSigner.SERVICE_SIGNING_NAME, "query-service")
+ .putSignerProperty(AwsV4HttpSigner.REGION_NAME, params.region().id()).build());
+ break;
+ }
+ return Collections.unmodifiableList(options);
+ }
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-params-with-allowlist.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-params-with-allowlist.java
new file mode 100644
index 000000000000..38d49f4851a5
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-params-with-allowlist.java
@@ -0,0 +1,105 @@
+/*
+ * 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.services.query.auth.scheme;
+
+import software.amazon.awssdk.annotations.Generated;
+import software.amazon.awssdk.annotations.SdkPublicApi;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.query.auth.scheme.internal.DefaultQueryAuthSchemeParams;
+import software.amazon.awssdk.utils.builder.CopyableBuilder;
+import software.amazon.awssdk.utils.builder.ToCopyableBuilder;
+
+/**
+ * The parameters object used to resolve the auth schemes for the Query service.
+ */
+@Generated("software.amazon.awssdk:codegen")
+@SdkPublicApi
+public interface QueryAuthSchemeParams extends ToCopyableBuilder {
+ /**
+ * Get a new builder for creating a {@link QueryAuthSchemeParams}.
+ */
+ static Builder builder() {
+ return DefaultQueryAuthSchemeParams.builder();
+ }
+
+ /**
+ * Returns the operation for which to resolve the auth scheme.
+ */
+ String operation();
+
+ /**
+ * Returns the region. The region parameter may be used with the "aws.auth#sigv4" auth scheme.
+ */
+ Region region();
+
+ /**
+ * A param that defauls to true
+ */
+ Boolean defaultTrueParam();
+
+ String defaultStringParam();
+
+ @Deprecated
+ String deprecatedParam();
+
+ Boolean booleanContextParam();
+
+ String stringContextParam();
+
+ String operationContextParam();
+
+ /**
+ * Returns a {@link Builder} to customize the parameters.
+ */
+ Builder toBuilder();
+
+ /**
+ * A builder for a {@link QueryAuthSchemeParams}.
+ */
+ interface Builder extends CopyableBuilder {
+ /**
+ * Set the operation for which to resolve the auth scheme.
+ */
+ Builder operation(String operation);
+
+ /**
+ * Set the region. The region parameter may be used with the "aws.auth#sigv4" auth scheme.
+ */
+ Builder region(Region region);
+
+ /**
+ * A param that defauls to true
+ */
+ Builder defaultTrueParam(Boolean defaultTrueParam);
+
+ Builder defaultStringParam(String defaultStringParam);
+
+ @Deprecated
+ Builder deprecatedParam(String deprecatedParam);
+
+ Builder booleanContextParam(Boolean booleanContextParam);
+
+ Builder stringContextParam(String stringContextParam);
+
+ Builder operationContextParam(String operationContextParam);
+
+ /**
+ * Returns a {@link QueryAuthSchemeParams} object that is created from the properties that have been set on the
+ * builder.
+ */
+ QueryAuthSchemeParams build();
+ }
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-params-without-allowlist.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-params-without-allowlist.java
new file mode 100644
index 000000000000..e9020e887cb6
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-params-without-allowlist.java
@@ -0,0 +1,117 @@
+/*
+ * 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.services.query.auth.scheme;
+
+import software.amazon.awssdk.annotations.Generated;
+import software.amazon.awssdk.annotations.SdkPublicApi;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.query.auth.scheme.internal.DefaultQueryAuthSchemeParams;
+import software.amazon.awssdk.utils.builder.CopyableBuilder;
+import software.amazon.awssdk.utils.builder.ToCopyableBuilder;
+
+/**
+ * The parameters object used to resolve the auth schemes for the Query service.
+ */
+@Generated("software.amazon.awssdk:codegen")
+@SdkPublicApi
+public interface QueryAuthSchemeParams extends ToCopyableBuilder {
+ /**
+ * Get a new builder for creating a {@link QueryAuthSchemeParams}.
+ */
+ static Builder builder() {
+ return DefaultQueryAuthSchemeParams.builder();
+ }
+
+ /**
+ * Returns the operation for which to resolve the auth scheme.
+ */
+ String operation();
+
+ /**
+ * Returns the region. The region parameter may be used with the "aws.auth#sigv4" auth scheme.
+ */
+ Region region();
+
+ Boolean useDualStackEndpoint();
+
+ Boolean useFipsEndpoint();
+
+ String endpointId();
+
+ /**
+ * A param that defauls to true
+ */
+ Boolean defaultTrueParam();
+
+ String defaultStringParam();
+
+ @Deprecated
+ String deprecatedParam();
+
+ Boolean booleanContextParam();
+
+ String stringContextParam();
+
+ String operationContextParam();
+
+ /**
+ * Returns a {@link Builder} to customize the parameters.
+ */
+ Builder toBuilder();
+
+ /**
+ * A builder for a {@link QueryAuthSchemeParams}.
+ */
+ interface Builder extends CopyableBuilder {
+ /**
+ * Set the operation for which to resolve the auth scheme.
+ */
+ Builder operation(String operation);
+
+ /**
+ * Set the region. The region parameter may be used with the "aws.auth#sigv4" auth scheme.
+ */
+ Builder region(Region region);
+
+ Builder useDualStackEndpoint(Boolean useDualStackEndpoint);
+
+ Builder useFipsEndpoint(Boolean useFIPSEndpoint);
+
+ Builder endpointId(String endpointId);
+
+ /**
+ * A param that defauls to true
+ */
+ Builder defaultTrueParam(Boolean defaultTrueParam);
+
+ Builder defaultStringParam(String defaultStringParam);
+
+ @Deprecated
+ Builder deprecatedParam(String deprecatedParam);
+
+ Builder booleanContextParam(Boolean booleanContextParam);
+
+ Builder stringContextParam(String stringContextParam);
+
+ Builder operationContextParam(String operationContextParam);
+
+ /**
+ * Returns a {@link QueryAuthSchemeParams} object that is created from the properties that have been set on the
+ * builder.
+ */
+ QueryAuthSchemeParams build();
+ }
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-provider.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-provider.java
new file mode 100644
index 000000000000..a4f84dc2665a
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-provider.java
@@ -0,0 +1,53 @@
+/*
+ * 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.services.query.auth.scheme;
+
+import java.util.List;
+import java.util.function.Consumer;
+import software.amazon.awssdk.annotations.Generated;
+import software.amazon.awssdk.annotations.SdkPublicApi;
+import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption;
+import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeProvider;
+import software.amazon.awssdk.services.query.auth.scheme.internal.DefaultQueryAuthSchemeProvider;
+
+/**
+ * An auth scheme provider for Query service. The auth scheme provider takes a set of parameters using
+ * {@link QueryAuthSchemeParams}, and resolves a list of {@link AuthSchemeOption} based on the given parameters.
+ */
+@Generated("software.amazon.awssdk:codegen")
+@SdkPublicApi
+public interface QueryAuthSchemeProvider extends AuthSchemeProvider {
+ /**
+ * Resolve the auth schemes based on the given set of parameters.
+ */
+ List resolveAuthScheme(QueryAuthSchemeParams authSchemeParams);
+
+ /**
+ * Resolve the auth schemes based on the given set of parameters.
+ */
+ default List resolveAuthScheme(Consumer consumer) {
+ QueryAuthSchemeParams.Builder builder = QueryAuthSchemeParams.builder();
+ consumer.accept(builder);
+ return resolveAuthScheme(builder.build());
+ }
+
+ /**
+ * Get the default auth scheme provider.
+ */
+ static QueryAuthSchemeProvider defaultProvider() {
+ return DefaultQueryAuthSchemeProvider.create();
+ }
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-with-allowlist-auth-scheme-interceptor.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-with-allowlist-auth-scheme-interceptor.java
new file mode 100644
index 000000000000..ac5ec58f59a7
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-with-allowlist-auth-scheme-interceptor.java
@@ -0,0 +1,137 @@
+package software.amazon.awssdk.services.query.auth.scheme.internal;
+
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+import software.amazon.awssdk.annotations.Generated;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.core.SdkRequest;
+import software.amazon.awssdk.core.SelectedAuthScheme;
+import software.amazon.awssdk.core.exception.SdkException;
+import software.amazon.awssdk.core.interceptor.Context;
+import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
+import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
+import software.amazon.awssdk.core.interceptor.SdkExecutionAttribute;
+import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute;
+import software.amazon.awssdk.core.internal.util.MetricUtils;
+import software.amazon.awssdk.core.metrics.CoreMetric;
+import software.amazon.awssdk.http.auth.spi.scheme.AuthScheme;
+import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption;
+import software.amazon.awssdk.identity.spi.AwsCredentialsIdentity;
+import software.amazon.awssdk.identity.spi.Identity;
+import software.amazon.awssdk.identity.spi.IdentityProvider;
+import software.amazon.awssdk.identity.spi.IdentityProviders;
+import software.amazon.awssdk.identity.spi.ResolveIdentityRequest;
+import software.amazon.awssdk.identity.spi.TokenIdentity;
+import software.amazon.awssdk.metrics.MetricCollector;
+import software.amazon.awssdk.metrics.SdkMetric;
+import software.amazon.awssdk.services.query.auth.scheme.QueryAuthSchemeParams;
+import software.amazon.awssdk.services.query.auth.scheme.QueryAuthSchemeProvider;
+import software.amazon.awssdk.services.query.endpoints.QueryEndpointParams;
+import software.amazon.awssdk.services.query.endpoints.internal.AuthSchemeUtils;
+import software.amazon.awssdk.services.query.endpoints.internal.QueryResolveEndpointInterceptor;
+import software.amazon.awssdk.utils.Logger;
+import software.amazon.awssdk.utils.Validate;
+
+@Generated("software.amazon.awssdk:codegen")
+@SdkInternalApi
+public final class QueryAuthSchemeInterceptor implements ExecutionInterceptor {
+ private static Logger LOG = Logger.loggerFor(QueryAuthSchemeInterceptor.class);
+
+ @Override
+ public void beforeExecution(Context.BeforeExecution context, ExecutionAttributes executionAttributes) {
+ List authOptions = resolveAuthOptions(context, executionAttributes);
+ SelectedAuthScheme extends Identity> selectedAuthScheme = selectAuthScheme(authOptions, executionAttributes);
+ AuthSchemeUtils.putSelectedAuthScheme(executionAttributes, selectedAuthScheme);
+ }
+
+ private List resolveAuthOptions(Context.BeforeExecution context, ExecutionAttributes executionAttributes) {
+ QueryAuthSchemeProvider authSchemeProvider = Validate.isInstanceOf(QueryAuthSchemeProvider.class,
+ executionAttributes.getAttribute(SdkInternalExecutionAttribute.AUTH_SCHEME_RESOLVER),
+ "Expected an instance of QueryAuthSchemeProvider");
+ QueryAuthSchemeParams params = authSchemeParams(context.request(), executionAttributes);
+ return authSchemeProvider.resolveAuthScheme(params);
+ }
+
+ private SelectedAuthScheme extends Identity> selectAuthScheme(List authOptions,
+ ExecutionAttributes executionAttributes) {
+ MetricCollector metricCollector = executionAttributes.getAttribute(SdkExecutionAttribute.API_CALL_METRIC_COLLECTOR);
+ Map> authSchemes = executionAttributes.getAttribute(SdkInternalExecutionAttribute.AUTH_SCHEMES);
+ IdentityProviders identityProviders = executionAttributes
+ .getAttribute(SdkInternalExecutionAttribute.IDENTITY_PROVIDERS);
+ List> discardedReasons = new ArrayList<>();
+ for (AuthSchemeOption authOption : authOptions) {
+ AuthScheme> authScheme = authSchemes.get(authOption.schemeId());
+ SelectedAuthScheme extends Identity> selectedAuthScheme = trySelectAuthScheme(authOption, authScheme,
+ identityProviders, discardedReasons, metricCollector);
+ if (selectedAuthScheme != null) {
+ if (!discardedReasons.isEmpty()) {
+ LOG.debug(() -> String.format("%s auth will be used, discarded: '%s'", authOption.schemeId(),
+ discardedReasons.stream().map(Supplier::get).collect(Collectors.joining(", "))));
+ }
+ return selectedAuthScheme;
+ }
+ }
+ throw SdkException
+ .builder()
+ .message(
+ "Failed to determine how to authenticate the user: "
+ + discardedReasons.stream().map(Supplier::get).collect(Collectors.joining(", "))).build();
+ }
+
+ private QueryAuthSchemeParams authSchemeParams(SdkRequest request, ExecutionAttributes executionAttributes) {
+ QueryEndpointParams endpointParams = QueryResolveEndpointInterceptor.ruleParams(request, executionAttributes);
+ QueryAuthSchemeParams.Builder builder = QueryAuthSchemeParams.builder();
+ builder.region(endpointParams.region());
+ builder.defaultTrueParam(endpointParams.defaultTrueParam());
+ builder.defaultStringParam(endpointParams.defaultStringParam());
+ builder.deprecatedParam(endpointParams.deprecatedParam());
+ builder.booleanContextParam(endpointParams.booleanContextParam());
+ builder.stringContextParam(endpointParams.stringContextParam());
+ builder.operationContextParam(endpointParams.operationContextParam());
+ String operation = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME);
+ builder.operation(operation);
+ return builder.build();
+ }
+
+ private SelectedAuthScheme trySelectAuthScheme(AuthSchemeOption authOption, AuthScheme authScheme,
+ IdentityProviders identityProviders, List> discardedReasons,
+ MetricCollector metricCollector) {
+ if (authScheme == null) {
+ discardedReasons.add(() -> String.format("'%s' is not enabled for this request.", authOption.schemeId()));
+ return null;
+ }
+ IdentityProvider identityProvider = authScheme.identityProvider(identityProviders);
+ if (identityProvider == null) {
+ discardedReasons
+ .add(() -> String.format("'%s' does not have an identity provider configured.", authOption.schemeId()));
+ return null;
+ }
+ ResolveIdentityRequest.Builder identityRequestBuilder = ResolveIdentityRequest.builder();
+ authOption.forEachIdentityProperty(identityRequestBuilder::putProperty);
+ CompletableFuture extends T> identity;
+ SdkMetric metric = getIdentityMetric(identityProvider);
+ if (metric == null) {
+ identity = identityProvider.resolveIdentity(identityRequestBuilder.build());
+ } else {
+ identity = MetricUtils.reportDuration(() -> identityProvider.resolveIdentity(identityRequestBuilder.build()),
+ metricCollector, metric);
+ }
+ return new SelectedAuthScheme<>(identity, authScheme.signer(), authOption);
+ }
+
+ private SdkMetric getIdentityMetric(IdentityProvider> identityProvider) {
+ Class> identityType = identityProvider.identityType();
+ if (identityType == AwsCredentialsIdentity.class) {
+ return CoreMetric.CREDENTIALS_FETCH_DURATION;
+ }
+ if (identityType == TokenIdentity.class) {
+ return CoreMetric.TOKEN_FETCH_DURATION;
+ }
+ return null;
+ }
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-without-allowlist-auth-scheme-interceptor.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-without-allowlist-auth-scheme-interceptor.java
new file mode 100644
index 000000000000..2399a2c48d81
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-without-allowlist-auth-scheme-interceptor.java
@@ -0,0 +1,140 @@
+package software.amazon.awssdk.services.query.auth.scheme.internal;
+
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+import software.amazon.awssdk.annotations.Generated;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.core.SdkRequest;
+import software.amazon.awssdk.core.SelectedAuthScheme;
+import software.amazon.awssdk.core.exception.SdkException;
+import software.amazon.awssdk.core.interceptor.Context;
+import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
+import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
+import software.amazon.awssdk.core.interceptor.SdkExecutionAttribute;
+import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute;
+import software.amazon.awssdk.core.internal.util.MetricUtils;
+import software.amazon.awssdk.core.metrics.CoreMetric;
+import software.amazon.awssdk.http.auth.spi.scheme.AuthScheme;
+import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption;
+import software.amazon.awssdk.identity.spi.AwsCredentialsIdentity;
+import software.amazon.awssdk.identity.spi.Identity;
+import software.amazon.awssdk.identity.spi.IdentityProvider;
+import software.amazon.awssdk.identity.spi.IdentityProviders;
+import software.amazon.awssdk.identity.spi.ResolveIdentityRequest;
+import software.amazon.awssdk.identity.spi.TokenIdentity;
+import software.amazon.awssdk.metrics.MetricCollector;
+import software.amazon.awssdk.metrics.SdkMetric;
+import software.amazon.awssdk.services.query.auth.scheme.QueryAuthSchemeParams;
+import software.amazon.awssdk.services.query.auth.scheme.QueryAuthSchemeProvider;
+import software.amazon.awssdk.services.query.endpoints.QueryEndpointParams;
+import software.amazon.awssdk.services.query.endpoints.internal.AuthSchemeUtils;
+import software.amazon.awssdk.services.query.endpoints.internal.QueryResolveEndpointInterceptor;
+import software.amazon.awssdk.utils.Logger;
+import software.amazon.awssdk.utils.Validate;
+
+@Generated("software.amazon.awssdk:codegen")
+@SdkInternalApi
+public final class QueryAuthSchemeInterceptor implements ExecutionInterceptor {
+ private static Logger LOG = Logger.loggerFor(QueryAuthSchemeInterceptor.class);
+
+ @Override
+ public void beforeExecution(Context.BeforeExecution context, ExecutionAttributes executionAttributes) {
+ List authOptions = resolveAuthOptions(context, executionAttributes);
+ SelectedAuthScheme extends Identity> selectedAuthScheme = selectAuthScheme(authOptions, executionAttributes);
+ AuthSchemeUtils.putSelectedAuthScheme(executionAttributes, selectedAuthScheme);
+ }
+
+ private List resolveAuthOptions(Context.BeforeExecution context, ExecutionAttributes executionAttributes) {
+ QueryAuthSchemeProvider authSchemeProvider = Validate.isInstanceOf(QueryAuthSchemeProvider.class,
+ executionAttributes.getAttribute(SdkInternalExecutionAttribute.AUTH_SCHEME_RESOLVER),
+ "Expected an instance of QueryAuthSchemeProvider");
+ QueryAuthSchemeParams params = authSchemeParams(context.request(), executionAttributes);
+ return authSchemeProvider.resolveAuthScheme(params);
+ }
+
+ private SelectedAuthScheme extends Identity> selectAuthScheme(List authOptions,
+ ExecutionAttributes executionAttributes) {
+ MetricCollector metricCollector = executionAttributes.getAttribute(SdkExecutionAttribute.API_CALL_METRIC_COLLECTOR);
+ Map> authSchemes = executionAttributes.getAttribute(SdkInternalExecutionAttribute.AUTH_SCHEMES);
+ IdentityProviders identityProviders = executionAttributes
+ .getAttribute(SdkInternalExecutionAttribute.IDENTITY_PROVIDERS);
+ List> discardedReasons = new ArrayList<>();
+ for (AuthSchemeOption authOption : authOptions) {
+ AuthScheme> authScheme = authSchemes.get(authOption.schemeId());
+ SelectedAuthScheme extends Identity> selectedAuthScheme = trySelectAuthScheme(authOption, authScheme,
+ identityProviders, discardedReasons, metricCollector);
+ if (selectedAuthScheme != null) {
+ if (!discardedReasons.isEmpty()) {
+ LOG.debug(() -> String.format("%s auth will be used, discarded: '%s'", authOption.schemeId(),
+ discardedReasons.stream().map(Supplier::get).collect(Collectors.joining(", "))));
+ }
+ return selectedAuthScheme;
+ }
+ }
+ throw SdkException
+ .builder()
+ .message(
+ "Failed to determine how to authenticate the user: "
+ + discardedReasons.stream().map(Supplier::get).collect(Collectors.joining(", "))).build();
+ }
+
+ private QueryAuthSchemeParams authSchemeParams(SdkRequest request, ExecutionAttributes executionAttributes) {
+ QueryEndpointParams endpointParams = QueryResolveEndpointInterceptor.ruleParams(request, executionAttributes);
+ QueryAuthSchemeParams.Builder builder = QueryAuthSchemeParams.builder();
+ builder.region(endpointParams.region());
+ builder.useDualStackEndpoint(endpointParams.useDualStackEndpoint());
+ builder.useFipsEndpoint(endpointParams.useFipsEndpoint());
+ builder.endpointId(endpointParams.endpointId());
+ builder.defaultTrueParam(endpointParams.defaultTrueParam());
+ builder.defaultStringParam(endpointParams.defaultStringParam());
+ builder.deprecatedParam(endpointParams.deprecatedParam());
+ builder.booleanContextParam(endpointParams.booleanContextParam());
+ builder.stringContextParam(endpointParams.stringContextParam());
+ builder.operationContextParam(endpointParams.operationContextParam());
+ String operation = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME);
+ builder.operation(operation);
+ return builder.build();
+ }
+
+ private SelectedAuthScheme trySelectAuthScheme(AuthSchemeOption authOption, AuthScheme authScheme,
+ IdentityProviders identityProviders, List> discardedReasons,
+ MetricCollector metricCollector) {
+ if (authScheme == null) {
+ discardedReasons.add(() -> String.format("'%s' is not enabled for this request.", authOption.schemeId()));
+ return null;
+ }
+ IdentityProvider identityProvider = authScheme.identityProvider(identityProviders);
+ if (identityProvider == null) {
+ discardedReasons
+ .add(() -> String.format("'%s' does not have an identity provider configured.", authOption.schemeId()));
+ return null;
+ }
+ ResolveIdentityRequest.Builder identityRequestBuilder = ResolveIdentityRequest.builder();
+ authOption.forEachIdentityProperty(identityRequestBuilder::putProperty);
+ CompletableFuture extends T> identity;
+ SdkMetric metric = getIdentityMetric(identityProvider);
+ if (metric == null) {
+ identity = identityProvider.resolveIdentity(identityRequestBuilder.build());
+ } else {
+ identity = MetricUtils.reportDuration(() -> identityProvider.resolveIdentity(identityRequestBuilder.build()),
+ metricCollector, metric);
+ }
+ return new SelectedAuthScheme<>(identity, authScheme.signer(), authOption);
+ }
+
+ private SdkMetric getIdentityMetric(IdentityProvider> identityProvider) {
+ Class> identityType = identityProvider.identityType();
+ if (identityType == AwsCredentialsIdentity.class) {
+ return CoreMetric.CREDENTIALS_FETCH_DURATION;
+ }
+ if (identityType == TokenIdentity.class) {
+ return CoreMetric.TOKEN_FETCH_DURATION;
+ }
+ return null;
+ }
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-bearer-auth-client-builder-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-bearer-auth-client-builder-class.java
new file mode 100644
index 000000000000..ee0924b32937
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-bearer-auth-client-builder-class.java
@@ -0,0 +1,153 @@
+package software.amazon.awssdk.services.json;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import software.amazon.awssdk.annotations.Generated;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.auth.token.credentials.aws.DefaultAwsTokenProvider;
+import software.amazon.awssdk.awscore.client.builder.AwsDefaultClientBuilder;
+import software.amazon.awssdk.awscore.client.config.AwsClientOption;
+import software.amazon.awssdk.core.SdkPlugin;
+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.interceptor.ClasspathInterceptorChainFactory;
+import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
+import software.amazon.awssdk.http.auth.scheme.BearerAuthScheme;
+import software.amazon.awssdk.http.auth.scheme.NoAuthAuthScheme;
+import software.amazon.awssdk.http.auth.spi.scheme.AuthScheme;
+import software.amazon.awssdk.identity.spi.IdentityProvider;
+import software.amazon.awssdk.identity.spi.IdentityProviders;
+import software.amazon.awssdk.identity.spi.TokenIdentity;
+import software.amazon.awssdk.services.json.auth.scheme.JsonAuthSchemeProvider;
+import software.amazon.awssdk.services.json.auth.scheme.internal.JsonAuthSchemeInterceptor;
+import software.amazon.awssdk.services.json.endpoints.JsonEndpointProvider;
+import software.amazon.awssdk.services.json.endpoints.internal.JsonRequestSetEndpointInterceptor;
+import software.amazon.awssdk.services.json.endpoints.internal.JsonResolveEndpointInterceptor;
+import software.amazon.awssdk.services.json.internal.JsonServiceClientConfigurationBuilder;
+import software.amazon.awssdk.services.json.internal.SdkClientConfigurationUtil;
+import software.amazon.awssdk.utils.CollectionUtils;
+import software.amazon.awssdk.utils.Validate;
+
+/**
+ * Internal base class for {@link DefaultJsonClientBuilder} and {@link DefaultJsonAsyncClientBuilder}.
+ */
+@Generated("software.amazon.awssdk:codegen")
+@SdkInternalApi
+abstract class DefaultJsonBaseClientBuilder, C> extends AwsDefaultClientBuilder {
+ private final Map> additionalAuthSchemes = new HashMap<>();
+
+ @Override
+ protected final String serviceEndpointPrefix() {
+ return "json-service-endpoint";
+ }
+
+ @Override
+ protected final String serviceName() {
+ return "Json";
+ }
+
+ @Override
+ protected final SdkClientConfiguration mergeServiceDefaults(SdkClientConfiguration config) {
+ return config.merge(c -> c.option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
+ .option(SdkClientOption.AUTH_SCHEME_PROVIDER, defaultAuthSchemeProvider())
+ .option(SdkClientOption.AUTH_SCHEMES, authSchemes())
+ .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false)
+ .option(AwsClientOption.TOKEN_IDENTITY_PROVIDER, defaultTokenProvider()));
+ }
+
+ @Override
+ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientConfiguration config) {
+ List endpointInterceptors = new ArrayList<>();
+ endpointInterceptors.add(new JsonAuthSchemeInterceptor());
+ endpointInterceptors.add(new JsonResolveEndpointInterceptor());
+ endpointInterceptors.add(new JsonRequestSetEndpointInterceptor());
+ ClasspathInterceptorChainFactory interceptorFactory = new ClasspathInterceptorChainFactory();
+ List interceptors = interceptorFactory
+ .getInterceptors("software/amazon/awssdk/services/json/execution.interceptors");
+ List additionalInterceptors = new ArrayList<>();
+ interceptors = CollectionUtils.mergeLists(endpointInterceptors, interceptors);
+ interceptors = CollectionUtils.mergeLists(interceptors, additionalInterceptors);
+ interceptors = CollectionUtils.mergeLists(interceptors, config.option(SdkClientOption.EXECUTION_INTERCEPTORS));
+ SdkClientConfiguration.Builder builder = config.toBuilder();
+ IdentityProvider extends TokenIdentity> identityProvider = config.option(AwsClientOption.TOKEN_IDENTITY_PROVIDER);
+ if (identityProvider != null) {
+ IdentityProviders identityProviders = config.option(SdkClientOption.IDENTITY_PROVIDERS);
+ builder.option(SdkClientOption.IDENTITY_PROVIDERS, identityProviders.toBuilder()
+ .putIdentityProvider(identityProvider).build());
+ }
+ builder.option(SdkClientOption.EXECUTION_INTERCEPTORS, interceptors);
+ return builder.build();
+ }
+
+ @Override
+ protected final String signingName() {
+ return "json-service";
+ }
+
+ private JsonEndpointProvider defaultEndpointProvider() {
+ return JsonEndpointProvider.defaultProvider();
+ }
+
+ public B authSchemeProvider(JsonAuthSchemeProvider authSchemeProvider) {
+ clientConfiguration.option(SdkClientOption.AUTH_SCHEME_PROVIDER, authSchemeProvider);
+ return thisBuilder();
+ }
+
+ private JsonAuthSchemeProvider defaultAuthSchemeProvider() {
+ return JsonAuthSchemeProvider.defaultProvider();
+ }
+
+ @Override
+ public B putAuthScheme(AuthScheme> authScheme) {
+ additionalAuthSchemes.put(authScheme.schemeId(), authScheme);
+ return thisBuilder();
+ }
+
+ private Map> authSchemes() {
+ Map> schemes = new HashMap<>(2 + this.additionalAuthSchemes.size());
+ BearerAuthScheme bearerAuthScheme = BearerAuthScheme.create();
+ schemes.put(bearerAuthScheme.schemeId(), bearerAuthScheme);
+ NoAuthAuthScheme noAuthAuthScheme = NoAuthAuthScheme.create();
+ schemes.put(noAuthAuthScheme.schemeId(), noAuthAuthScheme);
+ schemes.putAll(this.additionalAuthSchemes);
+ return Collections.unmodifiableMap(schemes);
+ }
+
+ private IdentityProvider extends TokenIdentity> defaultTokenProvider() {
+ return DefaultAwsTokenProvider.create();
+ }
+
+ @Override
+ protected SdkClientConfiguration setOverrides(SdkClientConfiguration configuration) {
+ ClientOverrideConfiguration overrideConfiguration = overrideConfiguration();
+ if (overrideConfiguration == null) {
+ return configuration;
+ }
+ return SdkClientConfigurationUtil.copyOverridesToConfiguration(overrideConfiguration, configuration.toBuilder()).build();
+ }
+
+ @Override
+ protected SdkClientConfiguration invokePlugins(SdkClientConfiguration config) {
+ List plugins = plugins();
+ if (plugins.isEmpty()) {
+ return config;
+ }
+ JsonServiceClientConfigurationBuilder.BuilderInternal serviceConfigBuilder = JsonServiceClientConfigurationBuilder
+ .builder(config.toBuilder());
+ serviceConfigBuilder.overrideConfiguration(overrideConfiguration());
+ for (SdkPlugin plugin : plugins) {
+ plugin.configureClient(serviceConfigBuilder);
+ }
+ overrideConfiguration(serviceConfigBuilder.overrideConfiguration());
+ return serviceConfigBuilder.buildSdkClientConfiguration();
+ }
+
+ protected static void validateClientOptions(SdkClientConfiguration c) {
+ Validate.notNull(c.option(AwsClientOption.TOKEN_IDENTITY_PROVIDER),
+ "The 'tokenProvider' must be configured in the client builder.");
+ }
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-client-builder-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-client-builder-class.java
new file mode 100644
index 000000000000..a59675c102b6
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-client-builder-class.java
@@ -0,0 +1,235 @@
+package software.amazon.awssdk.services.json;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import software.amazon.MyServiceHttpConfig;
+import software.amazon.MyServiceRetryPolicy;
+import software.amazon.awssdk.annotations.Generated;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.auth.token.credentials.aws.DefaultAwsTokenProvider;
+import software.amazon.awssdk.awscore.client.builder.AwsDefaultClientBuilder;
+import software.amazon.awssdk.awscore.client.config.AwsClientOption;
+import software.amazon.awssdk.core.SdkPlugin;
+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.interceptor.ClasspathInterceptorChainFactory;
+import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
+import software.amazon.awssdk.http.auth.aws.scheme.AwsV4AuthScheme;
+import software.amazon.awssdk.http.auth.scheme.BearerAuthScheme;
+import software.amazon.awssdk.http.auth.scheme.NoAuthAuthScheme;
+import software.amazon.awssdk.http.auth.spi.scheme.AuthScheme;
+import software.amazon.awssdk.identity.spi.IdentityProvider;
+import software.amazon.awssdk.identity.spi.IdentityProviders;
+import software.amazon.awssdk.identity.spi.TokenIdentity;
+import software.amazon.awssdk.services.json.auth.scheme.JsonAuthSchemeProvider;
+import software.amazon.awssdk.services.json.auth.scheme.internal.JsonAuthSchemeInterceptor;
+import software.amazon.awssdk.services.json.endpoints.JsonClientContextParams;
+import software.amazon.awssdk.services.json.endpoints.JsonEndpointProvider;
+import software.amazon.awssdk.services.json.endpoints.internal.JsonRequestSetEndpointInterceptor;
+import software.amazon.awssdk.services.json.endpoints.internal.JsonResolveEndpointInterceptor;
+import software.amazon.awssdk.services.json.internal.JsonServiceClientConfigurationBuilder;
+import software.amazon.awssdk.services.json.internal.SdkClientConfigurationUtil;
+import software.amazon.awssdk.utils.AttributeMap;
+import software.amazon.awssdk.utils.CollectionUtils;
+import software.amazon.awssdk.utils.Validate;
+
+/**
+ * Internal base class for {@link DefaultJsonClientBuilder} and {@link DefaultJsonAsyncClientBuilder}.
+ */
+@Generated("software.amazon.awssdk:codegen")
+@SdkInternalApi
+abstract class DefaultJsonBaseClientBuilder, C> extends AwsDefaultClientBuilder {
+ private final Map> additionalAuthSchemes = new HashMap<>();
+
+ @Override
+ protected final String serviceEndpointPrefix() {
+ return "json-service-endpoint";
+ }
+
+ @Override
+ protected final String serviceName() {
+ return "Json";
+ }
+
+ @Override
+ protected final SdkClientConfiguration mergeServiceDefaults(SdkClientConfiguration config) {
+ return config.merge(c -> c.option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
+ .option(SdkClientOption.AUTH_SCHEME_PROVIDER, defaultAuthSchemeProvider())
+ .option(SdkClientOption.AUTH_SCHEMES, authSchemes())
+ .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false)
+ .option(SdkClientOption.SERVICE_CONFIGURATION, ServiceConfiguration.builder().build())
+ .option(AwsClientOption.TOKEN_IDENTITY_PROVIDER, defaultTokenProvider()));
+ }
+
+ @Override
+ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientConfiguration config) {
+ List endpointInterceptors = new ArrayList<>();
+ endpointInterceptors.add(new JsonAuthSchemeInterceptor());
+ endpointInterceptors.add(new JsonResolveEndpointInterceptor());
+ endpointInterceptors.add(new JsonRequestSetEndpointInterceptor());
+ ClasspathInterceptorChainFactory interceptorFactory = new ClasspathInterceptorChainFactory();
+ List interceptors = interceptorFactory
+ .getInterceptors("software/amazon/awssdk/services/json/execution.interceptors");
+ List additionalInterceptors = new ArrayList<>();
+ interceptors = CollectionUtils.mergeLists(endpointInterceptors, interceptors);
+ interceptors = CollectionUtils.mergeLists(interceptors, additionalInterceptors);
+ interceptors = CollectionUtils.mergeLists(interceptors, config.option(SdkClientOption.EXECUTION_INTERCEPTORS));
+ ServiceConfiguration.Builder serviceConfigBuilder = ((ServiceConfiguration) config
+ .option(SdkClientOption.SERVICE_CONFIGURATION)).toBuilder();
+ serviceConfigBuilder.profileFile(serviceConfigBuilder.profileFileSupplier() != null ? serviceConfigBuilder
+ .profileFileSupplier() : config.option(SdkClientOption.PROFILE_FILE_SUPPLIER));
+ serviceConfigBuilder.profileName(serviceConfigBuilder.profileName() != null ? serviceConfigBuilder.profileName() : config
+ .option(SdkClientOption.PROFILE_NAME));
+ if (serviceConfigBuilder.dualstackEnabled() != null) {
+ Validate.validState(
+ config.option(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED) == null,
+ "Dualstack has been configured on both ServiceConfiguration and the client/global level. Please limit dualstack configuration to one location.");
+ } else {
+ serviceConfigBuilder.dualstackEnabled(config.option(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED));
+ }
+ if (serviceConfigBuilder.fipsModeEnabled() != null) {
+ Validate.validState(
+ config.option(AwsClientOption.FIPS_ENDPOINT_ENABLED) == null,
+ "Fips has been configured on both ServiceConfiguration and the client/global level. Please limit fips configuration to one location.");
+ } else {
+ serviceConfigBuilder.fipsModeEnabled(config.option(AwsClientOption.FIPS_ENDPOINT_ENABLED));
+ }
+ if (serviceConfigBuilder.useArnRegionEnabled() != null) {
+ Validate.validState(
+ clientContextParams.get(JsonClientContextParams.USE_ARN_REGION) == null,
+ "UseArnRegion has been configured on both ServiceConfiguration and the client/global level. Please limit UseArnRegion configuration to one location.");
+ } else {
+ serviceConfigBuilder.useArnRegionEnabled(clientContextParams.get(JsonClientContextParams.USE_ARN_REGION));
+ }
+ if (serviceConfigBuilder.multiRegionEnabled() != null) {
+ Validate.validState(
+ clientContextParams.get(JsonClientContextParams.DISABLE_MULTI_REGION_ACCESS_POINTS) == null,
+ "DisableMultiRegionAccessPoints has been configured on both ServiceConfiguration and the client/global level. Please limit DisableMultiRegionAccessPoints configuration to one location.");
+ } else if (clientContextParams.get(JsonClientContextParams.DISABLE_MULTI_REGION_ACCESS_POINTS) != null) {
+ serviceConfigBuilder.multiRegionEnabled(!clientContextParams
+ .get(JsonClientContextParams.DISABLE_MULTI_REGION_ACCESS_POINTS));
+ }
+ if (serviceConfigBuilder.pathStyleAccessEnabled() != null) {
+ Validate.validState(
+ clientContextParams.get(JsonClientContextParams.FORCE_PATH_STYLE) == null,
+ "ForcePathStyle has been configured on both ServiceConfiguration and the client/global level. Please limit ForcePathStyle configuration to one location.");
+ } else {
+ serviceConfigBuilder.pathStyleAccessEnabled(clientContextParams.get(JsonClientContextParams.FORCE_PATH_STYLE));
+ }
+ if (serviceConfigBuilder.accelerateModeEnabled() != null) {
+ Validate.validState(
+ clientContextParams.get(JsonClientContextParams.ACCELERATE) == null,
+ "Accelerate has been configured on both ServiceConfiguration and the client/global level. Please limit Accelerate configuration to one location.");
+ } else {
+ serviceConfigBuilder.accelerateModeEnabled(clientContextParams.get(JsonClientContextParams.ACCELERATE));
+ }
+ ServiceConfiguration finalServiceConfig = serviceConfigBuilder.build();
+ clientContextParams.put(JsonClientContextParams.USE_ARN_REGION, finalServiceConfig.useArnRegionEnabled());
+ clientContextParams.put(JsonClientContextParams.DISABLE_MULTI_REGION_ACCESS_POINTS,
+ !finalServiceConfig.multiRegionEnabled());
+ clientContextParams.put(JsonClientContextParams.FORCE_PATH_STYLE, finalServiceConfig.pathStyleAccessEnabled());
+ clientContextParams.put(JsonClientContextParams.ACCELERATE, finalServiceConfig.accelerateModeEnabled());
+ SdkClientConfiguration.Builder builder = config.toBuilder();
+ IdentityProvider extends TokenIdentity> identityProvider = config.option(AwsClientOption.TOKEN_IDENTITY_PROVIDER);
+ if (identityProvider != null) {
+ IdentityProviders identityProviders = config.option(SdkClientOption.IDENTITY_PROVIDERS);
+ builder.option(SdkClientOption.IDENTITY_PROVIDERS, identityProviders.toBuilder()
+ .putIdentityProvider(identityProvider).build());
+ }
+ builder.option(SdkClientOption.EXECUTION_INTERCEPTORS, interceptors)
+ .option(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED, finalServiceConfig.dualstackEnabled())
+ .option(AwsClientOption.FIPS_ENDPOINT_ENABLED, finalServiceConfig.fipsModeEnabled())
+ .option(SdkClientOption.RETRY_POLICY, MyServiceRetryPolicy.resolveRetryPolicy(config))
+ .option(SdkClientOption.SERVICE_CONFIGURATION, finalServiceConfig);
+ return builder.build();
+ }
+
+ @Override
+ protected final String signingName() {
+ return "json-service";
+ }
+
+ private JsonEndpointProvider defaultEndpointProvider() {
+ return JsonEndpointProvider.defaultProvider();
+ }
+
+ public B authSchemeProvider(JsonAuthSchemeProvider authSchemeProvider) {
+ clientConfiguration.option(SdkClientOption.AUTH_SCHEME_PROVIDER, authSchemeProvider);
+ return thisBuilder();
+ }
+
+ private JsonAuthSchemeProvider defaultAuthSchemeProvider() {
+ return JsonAuthSchemeProvider.defaultProvider();
+ }
+
+ @Override
+ public B putAuthScheme(AuthScheme> authScheme) {
+ additionalAuthSchemes.put(authScheme.schemeId(), authScheme);
+ return thisBuilder();
+ }
+
+ private Map> authSchemes() {
+ Map> schemes = new HashMap<>(3 + this.additionalAuthSchemes.size());
+ AwsV4AuthScheme awsV4AuthScheme = AwsV4AuthScheme.create();
+ schemes.put(awsV4AuthScheme.schemeId(), awsV4AuthScheme);
+ BearerAuthScheme bearerAuthScheme = BearerAuthScheme.create();
+ schemes.put(bearerAuthScheme.schemeId(), bearerAuthScheme);
+ NoAuthAuthScheme noAuthAuthScheme = NoAuthAuthScheme.create();
+ schemes.put(noAuthAuthScheme.schemeId(), noAuthAuthScheme);
+ schemes.putAll(this.additionalAuthSchemes);
+ return Collections.unmodifiableMap(schemes);
+ }
+
+ public B serviceConfiguration(ServiceConfiguration serviceConfiguration) {
+ clientConfiguration.option(SdkClientOption.SERVICE_CONFIGURATION, serviceConfiguration);
+ return thisBuilder();
+ }
+
+ public void setServiceConfiguration(ServiceConfiguration serviceConfiguration) {
+ serviceConfiguration(serviceConfiguration);
+ }
+
+ private IdentityProvider extends TokenIdentity> defaultTokenProvider() {
+ return DefaultAwsTokenProvider.create();
+ }
+
+ @Override
+ protected SdkClientConfiguration setOverrides(SdkClientConfiguration configuration) {
+ ClientOverrideConfiguration overrideConfiguration = overrideConfiguration();
+ if (overrideConfiguration == null) {
+ return configuration;
+ }
+ return SdkClientConfigurationUtil.copyOverridesToConfiguration(overrideConfiguration, configuration.toBuilder()).build();
+ }
+
+ @Override
+ protected final AttributeMap serviceHttpConfig() {
+ AttributeMap result = MyServiceHttpConfig.defaultHttpConfig();
+ return result;
+ }
+
+ @Override
+ protected SdkClientConfiguration invokePlugins(SdkClientConfiguration config) {
+ List plugins = plugins();
+ if (plugins.isEmpty()) {
+ return config;
+ }
+ JsonServiceClientConfigurationBuilder.BuilderInternal serviceConfigBuilder = JsonServiceClientConfigurationBuilder
+ .builder(config.toBuilder());
+ serviceConfigBuilder.overrideConfiguration(overrideConfiguration());
+ for (SdkPlugin plugin : plugins) {
+ plugin.configureClient(serviceConfigBuilder);
+ }
+ overrideConfiguration(serviceConfigBuilder.overrideConfiguration());
+ return serviceConfigBuilder.buildSdkClientConfiguration();
+ }
+
+ protected static void validateClientOptions(SdkClientConfiguration c) {
+ Validate.notNull(c.option(AwsClientOption.TOKEN_IDENTITY_PROVIDER),
+ "The 'tokenProvider' must be configured in the client builder.");
+ }
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-client-builder-endpoints-auth-params.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-client-builder-endpoints-auth-params.java
new file mode 100644
index 000000000000..322429dc737a
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-client-builder-endpoints-auth-params.java
@@ -0,0 +1,174 @@
+package software.amazon.awssdk.services.query;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import software.amazon.awssdk.annotations.Generated;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.auth.token.credentials.aws.DefaultAwsTokenProvider;
+import software.amazon.awssdk.awscore.client.builder.AwsDefaultClientBuilder;
+import software.amazon.awssdk.awscore.client.config.AwsClientOption;
+import software.amazon.awssdk.core.SdkPlugin;
+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.interceptor.ClasspathInterceptorChainFactory;
+import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
+import software.amazon.awssdk.http.auth.aws.scheme.AwsV4AuthScheme;
+import software.amazon.awssdk.http.auth.aws.scheme.AwsV4aAuthScheme;
+import software.amazon.awssdk.http.auth.scheme.BearerAuthScheme;
+import software.amazon.awssdk.http.auth.scheme.NoAuthAuthScheme;
+import software.amazon.awssdk.http.auth.spi.scheme.AuthScheme;
+import software.amazon.awssdk.identity.spi.IdentityProvider;
+import software.amazon.awssdk.identity.spi.IdentityProviders;
+import software.amazon.awssdk.identity.spi.TokenIdentity;
+import software.amazon.awssdk.protocols.query.interceptor.QueryParametersToBodyInterceptor;
+import software.amazon.awssdk.services.query.auth.scheme.QueryAuthSchemeProvider;
+import software.amazon.awssdk.services.query.auth.scheme.internal.QueryAuthSchemeInterceptor;
+import software.amazon.awssdk.services.query.endpoints.QueryClientContextParams;
+import software.amazon.awssdk.services.query.endpoints.QueryEndpointProvider;
+import software.amazon.awssdk.services.query.endpoints.internal.QueryRequestSetEndpointInterceptor;
+import software.amazon.awssdk.services.query.endpoints.internal.QueryResolveEndpointInterceptor;
+import software.amazon.awssdk.services.query.internal.QueryServiceClientConfigurationBuilder;
+import software.amazon.awssdk.services.query.internal.SdkClientConfigurationUtil;
+import software.amazon.awssdk.utils.CollectionUtils;
+import software.amazon.awssdk.utils.Validate;
+
+/**
+ * Internal base class for {@link DefaultQueryClientBuilder} and {@link DefaultQueryAsyncClientBuilder}.
+ */
+@Generated("software.amazon.awssdk:codegen")
+@SdkInternalApi
+abstract class DefaultQueryBaseClientBuilder, C> extends AwsDefaultClientBuilder {
+ private final Map> additionalAuthSchemes = new HashMap<>();
+
+ @Override
+ protected final String serviceEndpointPrefix() {
+ return "query-service";
+ }
+
+ @Override
+ protected final String serviceName() {
+ return "Query";
+ }
+
+ @Override
+ protected final SdkClientConfiguration mergeServiceDefaults(SdkClientConfiguration config) {
+ return config.merge(c -> c.option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
+ .option(SdkClientOption.AUTH_SCHEME_PROVIDER, defaultAuthSchemeProvider())
+ .option(SdkClientOption.AUTH_SCHEMES, authSchemes())
+ .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false)
+ .option(AwsClientOption.TOKEN_IDENTITY_PROVIDER, defaultTokenProvider()));
+ }
+
+ @Override
+ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientConfiguration config) {
+ List endpointInterceptors = new ArrayList<>();
+ endpointInterceptors.add(new QueryAuthSchemeInterceptor());
+ endpointInterceptors.add(new QueryResolveEndpointInterceptor());
+ endpointInterceptors.add(new QueryRequestSetEndpointInterceptor());
+ ClasspathInterceptorChainFactory interceptorFactory = new ClasspathInterceptorChainFactory();
+ List interceptors = interceptorFactory
+ .getInterceptors("software/amazon/awssdk/services/query/execution.interceptors");
+ List additionalInterceptors = new ArrayList<>();
+ interceptors = CollectionUtils.mergeLists(endpointInterceptors, interceptors);
+ interceptors = CollectionUtils.mergeLists(interceptors, additionalInterceptors);
+ interceptors = CollectionUtils.mergeLists(interceptors, config.option(SdkClientOption.EXECUTION_INTERCEPTORS));
+ List protocolInterceptors = Collections.singletonList(new QueryParametersToBodyInterceptor());
+ interceptors = CollectionUtils.mergeLists(interceptors, protocolInterceptors);
+ SdkClientConfiguration.Builder builder = config.toBuilder();
+ IdentityProvider extends TokenIdentity> identityProvider = config.option(AwsClientOption.TOKEN_IDENTITY_PROVIDER);
+ if (identityProvider != null) {
+ IdentityProviders identityProviders = config.option(SdkClientOption.IDENTITY_PROVIDERS);
+ builder.option(SdkClientOption.IDENTITY_PROVIDERS, identityProviders.toBuilder()
+ .putIdentityProvider(identityProvider).build());
+ }
+ builder.option(SdkClientOption.EXECUTION_INTERCEPTORS, interceptors).option(SdkClientOption.CLIENT_CONTEXT_PARAMS,
+ clientContextParams.build());
+ return builder.build();
+ }
+
+ @Override
+ protected final String signingName() {
+ return "query-service";
+ }
+
+ private QueryEndpointProvider defaultEndpointProvider() {
+ return QueryEndpointProvider.defaultProvider();
+ }
+
+ public B authSchemeProvider(QueryAuthSchemeProvider authSchemeProvider) {
+ clientConfiguration.option(SdkClientOption.AUTH_SCHEME_PROVIDER, authSchemeProvider);
+ return thisBuilder();
+ }
+
+ private QueryAuthSchemeProvider defaultAuthSchemeProvider() {
+ return QueryAuthSchemeProvider.defaultProvider();
+ }
+
+ @Override
+ public B putAuthScheme(AuthScheme> authScheme) {
+ additionalAuthSchemes.put(authScheme.schemeId(), authScheme);
+ return thisBuilder();
+ }
+
+ private Map> authSchemes() {
+ Map> schemes = new HashMap<>(4 + this.additionalAuthSchemes.size());
+ AwsV4AuthScheme awsV4AuthScheme = AwsV4AuthScheme.create();
+ schemes.put(awsV4AuthScheme.schemeId(), awsV4AuthScheme);
+ AwsV4aAuthScheme awsV4aAuthScheme = AwsV4aAuthScheme.create();
+ schemes.put(awsV4aAuthScheme.schemeId(), awsV4aAuthScheme);
+ BearerAuthScheme bearerAuthScheme = BearerAuthScheme.create();
+ schemes.put(bearerAuthScheme.schemeId(), bearerAuthScheme);
+ NoAuthAuthScheme noAuthAuthScheme = NoAuthAuthScheme.create();
+ schemes.put(noAuthAuthScheme.schemeId(), noAuthAuthScheme);
+ schemes.putAll(this.additionalAuthSchemes);
+ return Collections.unmodifiableMap(schemes);
+ }
+
+ public B booleanContextParam(Boolean booleanContextParam) {
+ clientContextParams.put(QueryClientContextParams.BOOLEAN_CONTEXT_PARAM, booleanContextParam);
+ return thisBuilder();
+ }
+
+ public B stringContextParam(String stringContextParam) {
+ clientContextParams.put(QueryClientContextParams.STRING_CONTEXT_PARAM, stringContextParam);
+ return thisBuilder();
+ }
+
+ private IdentityProvider extends TokenIdentity> defaultTokenProvider() {
+ return DefaultAwsTokenProvider.create();
+ }
+
+ @Override
+ protected SdkClientConfiguration setOverrides(SdkClientConfiguration configuration) {
+ ClientOverrideConfiguration overrideConfiguration = overrideConfiguration();
+ if (overrideConfiguration == null) {
+ return configuration;
+ }
+ return SdkClientConfigurationUtil.copyOverridesToConfiguration(overrideConfiguration, configuration.toBuilder()).build();
+ }
+
+ @Override
+ protected SdkClientConfiguration invokePlugins(SdkClientConfiguration config) {
+ List plugins = plugins();
+ if (plugins.isEmpty()) {
+ return config;
+ }
+ QueryServiceClientConfigurationBuilder.BuilderInternal serviceConfigBuilder = QueryServiceClientConfigurationBuilder
+ .builder(config.toBuilder());
+ serviceConfigBuilder.overrideConfiguration(overrideConfiguration());
+ for (SdkPlugin plugin : plugins) {
+ plugin.configureClient(serviceConfigBuilder);
+ }
+ overrideConfiguration(serviceConfigBuilder.overrideConfiguration());
+ return serviceConfigBuilder.buildSdkClientConfiguration();
+ }
+
+ protected static void validateClientOptions(SdkClientConfiguration c) {
+ Validate.notNull(c.option(AwsClientOption.TOKEN_IDENTITY_PROVIDER),
+ "The 'tokenProvider' must be configured in the client builder.");
+ }
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-client-builder-internal-defaults-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-client-builder-internal-defaults-class.java
new file mode 100644
index 000000000000..217c98e28c7c
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-client-builder-internal-defaults-class.java
@@ -0,0 +1,143 @@
+package software.amazon.awssdk.services.json;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import software.amazon.awssdk.annotations.Generated;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.awscore.client.builder.AwsDefaultClientBuilder;
+import software.amazon.awssdk.core.SdkPlugin;
+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.interceptor.ClasspathInterceptorChainFactory;
+import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
+import software.amazon.awssdk.core.retry.RetryMode;
+import software.amazon.awssdk.http.auth.aws.scheme.AwsV4AuthScheme;
+import software.amazon.awssdk.http.auth.scheme.NoAuthAuthScheme;
+import software.amazon.awssdk.http.auth.spi.scheme.AuthScheme;
+import software.amazon.awssdk.services.json.auth.scheme.JsonAuthSchemeProvider;
+import software.amazon.awssdk.services.json.auth.scheme.internal.JsonAuthSchemeInterceptor;
+import software.amazon.awssdk.services.json.endpoints.JsonEndpointProvider;
+import software.amazon.awssdk.services.json.endpoints.internal.JsonRequestSetEndpointInterceptor;
+import software.amazon.awssdk.services.json.endpoints.internal.JsonResolveEndpointInterceptor;
+import software.amazon.awssdk.services.json.internal.JsonServiceClientConfigurationBuilder;
+import software.amazon.awssdk.services.json.internal.SdkClientConfigurationUtil;
+import software.amazon.awssdk.utils.CollectionUtils;
+
+/**
+ * Internal base class for {@link DefaultJsonClientBuilder} and {@link DefaultJsonAsyncClientBuilder}.
+ */
+@Generated("software.amazon.awssdk:codegen")
+@SdkInternalApi
+abstract class DefaultJsonBaseClientBuilder, C> extends AwsDefaultClientBuilder {
+ private final Map> additionalAuthSchemes = new HashMap<>();
+
+ @Override
+ protected final String serviceEndpointPrefix() {
+ return "json-service-endpoint";
+ }
+
+ @Override
+ protected final String serviceName() {
+ return "Json";
+ }
+
+ @Override
+ protected final SdkClientConfiguration mergeServiceDefaults(SdkClientConfiguration config) {
+ return config.merge(c -> c.option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
+ .option(SdkClientOption.AUTH_SCHEME_PROVIDER, defaultAuthSchemeProvider())
+ .option(SdkClientOption.AUTH_SCHEMES, authSchemes())
+ .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false));
+ }
+
+ @Override
+ protected final SdkClientConfiguration mergeInternalDefaults(SdkClientConfiguration config) {
+ return config.merge(c -> {
+ c.option(SdkClientOption.INTERNAL_USER_AGENT, "md/foobar");
+ c.option(SdkClientOption.DEFAULT_RETRY_MODE, RetryMode.STANDARD);
+ });
+ }
+
+ @Override
+ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientConfiguration config) {
+ List endpointInterceptors = new ArrayList<>();
+ endpointInterceptors.add(new JsonAuthSchemeInterceptor());
+ endpointInterceptors.add(new JsonResolveEndpointInterceptor());
+ endpointInterceptors.add(new JsonRequestSetEndpointInterceptor());
+ ClasspathInterceptorChainFactory interceptorFactory = new ClasspathInterceptorChainFactory();
+ List interceptors = interceptorFactory
+ .getInterceptors("software/amazon/awssdk/services/json/execution.interceptors");
+ List additionalInterceptors = new ArrayList<>();
+ interceptors = CollectionUtils.mergeLists(endpointInterceptors, interceptors);
+ interceptors = CollectionUtils.mergeLists(interceptors, additionalInterceptors);
+ interceptors = CollectionUtils.mergeLists(interceptors, config.option(SdkClientOption.EXECUTION_INTERCEPTORS));
+ SdkClientConfiguration.Builder builder = config.toBuilder();
+ builder.option(SdkClientOption.EXECUTION_INTERCEPTORS, interceptors);
+ return builder.build();
+ }
+
+ @Override
+ protected final String signingName() {
+ return "json-service";
+ }
+
+ private JsonEndpointProvider defaultEndpointProvider() {
+ return JsonEndpointProvider.defaultProvider();
+ }
+
+ public B authSchemeProvider(JsonAuthSchemeProvider authSchemeProvider) {
+ clientConfiguration.option(SdkClientOption.AUTH_SCHEME_PROVIDER, authSchemeProvider);
+ return thisBuilder();
+ }
+
+ private JsonAuthSchemeProvider defaultAuthSchemeProvider() {
+ return JsonAuthSchemeProvider.defaultProvider();
+ }
+
+ @Override
+ public B putAuthScheme(AuthScheme> authScheme) {
+ additionalAuthSchemes.put(authScheme.schemeId(), authScheme);
+ return thisBuilder();
+ }
+
+ private Map> authSchemes() {
+ Map> schemes = new HashMap<>(2 + this.additionalAuthSchemes.size());
+ AwsV4AuthScheme awsV4AuthScheme = AwsV4AuthScheme.create();
+ schemes.put(awsV4AuthScheme.schemeId(), awsV4AuthScheme);
+ NoAuthAuthScheme noAuthAuthScheme = NoAuthAuthScheme.create();
+ schemes.put(noAuthAuthScheme.schemeId(), noAuthAuthScheme);
+ schemes.putAll(this.additionalAuthSchemes);
+ return Collections.unmodifiableMap(schemes);
+ }
+
+ @Override
+ protected SdkClientConfiguration setOverrides(SdkClientConfiguration configuration) {
+ ClientOverrideConfiguration overrideConfiguration = overrideConfiguration();
+ if (overrideConfiguration == null) {
+ return configuration;
+ }
+ return SdkClientConfigurationUtil.copyOverridesToConfiguration(overrideConfiguration, configuration.toBuilder()).build();
+ }
+
+ @Override
+ protected SdkClientConfiguration invokePlugins(SdkClientConfiguration config) {
+ List plugins = plugins();
+ if (plugins.isEmpty()) {
+ return config;
+ }
+ JsonServiceClientConfigurationBuilder.BuilderInternal serviceConfigBuilder = JsonServiceClientConfigurationBuilder
+ .builder(config.toBuilder());
+ serviceConfigBuilder.overrideConfiguration(overrideConfiguration());
+ for (SdkPlugin plugin : plugins) {
+ plugin.configureClient(serviceConfigBuilder);
+ }
+ overrideConfiguration(serviceConfigBuilder.overrideConfiguration());
+ return serviceConfigBuilder.buildSdkClientConfiguration();
+ }
+
+ protected static void validateClientOptions(SdkClientConfiguration c) {
+ }
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-composed-sync-default-client-builder.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-composed-sync-default-client-builder.java
new file mode 100644
index 000000000000..53bac0194568
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-composed-sync-default-client-builder.java
@@ -0,0 +1,180 @@
+package software.amazon.awssdk.services.json;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import software.amazon.awssdk.annotations.Generated;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.auth.token.credentials.aws.DefaultAwsTokenProvider;
+import software.amazon.awssdk.awscore.client.builder.AwsDefaultClientBuilder;
+import software.amazon.awssdk.awscore.client.config.AwsClientOption;
+import software.amazon.awssdk.core.SdkPlugin;
+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.interceptor.ClasspathInterceptorChainFactory;
+import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
+import software.amazon.awssdk.http.auth.aws.scheme.AwsV4AuthScheme;
+import software.amazon.awssdk.http.auth.scheme.BearerAuthScheme;
+import software.amazon.awssdk.http.auth.scheme.NoAuthAuthScheme;
+import software.amazon.awssdk.http.auth.spi.scheme.AuthScheme;
+import software.amazon.awssdk.identity.spi.IdentityProvider;
+import software.amazon.awssdk.identity.spi.IdentityProviders;
+import software.amazon.awssdk.identity.spi.TokenIdentity;
+import software.amazon.awssdk.services.json.auth.scheme.JsonAuthSchemeProvider;
+import software.amazon.awssdk.services.json.auth.scheme.internal.JsonAuthSchemeInterceptor;
+import software.amazon.awssdk.services.json.endpoints.JsonClientContextParams;
+import software.amazon.awssdk.services.json.endpoints.JsonEndpointProvider;
+import software.amazon.awssdk.services.json.endpoints.internal.JsonRequestSetEndpointInterceptor;
+import software.amazon.awssdk.services.json.endpoints.internal.JsonResolveEndpointInterceptor;
+import software.amazon.awssdk.services.json.internal.JsonServiceClientConfigurationBuilder;
+import software.amazon.awssdk.services.json.internal.SdkClientConfigurationUtil;
+import software.amazon.awssdk.utils.CollectionUtils;
+import software.amazon.awssdk.utils.Validate;
+
+/**
+ * Internal base class for {@link DefaultJsonClientBuilder} and {@link DefaultJsonAsyncClientBuilder}.
+ */
+@Generated("software.amazon.awssdk:codegen")
+@SdkInternalApi
+abstract class DefaultJsonBaseClientBuilder, C> extends AwsDefaultClientBuilder {
+ private final Map> additionalAuthSchemes = new HashMap<>();
+
+ @Override
+ protected final String serviceEndpointPrefix() {
+ return "json-service-endpoint";
+ }
+
+ @Override
+ protected final String serviceName() {
+ return "Json";
+ }
+
+ @Override
+ protected final SdkClientConfiguration mergeServiceDefaults(SdkClientConfiguration config) {
+ return config.merge(c -> c.option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
+ .option(SdkClientOption.AUTH_SCHEME_PROVIDER, defaultAuthSchemeProvider())
+ .option(SdkClientOption.AUTH_SCHEMES, authSchemes())
+ .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false)
+ .option(SdkClientOption.SERVICE_CONFIGURATION, ServiceConfiguration.builder().build())
+ .option(AwsClientOption.TOKEN_IDENTITY_PROVIDER, defaultTokenProvider()));
+ }
+
+ @Override
+ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientConfiguration config) {
+ List endpointInterceptors = new ArrayList<>();
+ endpointInterceptors.add(new JsonAuthSchemeInterceptor());
+ endpointInterceptors.add(new JsonResolveEndpointInterceptor());
+ endpointInterceptors.add(new JsonRequestSetEndpointInterceptor());
+ ClasspathInterceptorChainFactory interceptorFactory = new ClasspathInterceptorChainFactory();
+ List interceptors = interceptorFactory
+ .getInterceptors("software/amazon/awssdk/services/json/execution.interceptors");
+ List additionalInterceptors = new ArrayList<>();
+ interceptors = CollectionUtils.mergeLists(endpointInterceptors, interceptors);
+ interceptors = CollectionUtils.mergeLists(interceptors, additionalInterceptors);
+ interceptors = CollectionUtils.mergeLists(interceptors, config.option(SdkClientOption.EXECUTION_INTERCEPTORS));
+ ServiceConfiguration.Builder serviceConfigBuilder = ((ServiceConfiguration) config
+ .option(SdkClientOption.SERVICE_CONFIGURATION)).toBuilder();
+ serviceConfigBuilder.profileFile(serviceConfigBuilder.profileFileSupplier() != null ? serviceConfigBuilder
+ .profileFileSupplier() : config.option(SdkClientOption.PROFILE_FILE_SUPPLIER));
+ serviceConfigBuilder.profileName(serviceConfigBuilder.profileName() != null ? serviceConfigBuilder.profileName() : config
+ .option(SdkClientOption.PROFILE_NAME));
+ ServiceConfiguration finalServiceConfig = serviceConfigBuilder.build();
+ SdkClientConfiguration.Builder builder = config.toBuilder();
+ IdentityProvider extends TokenIdentity> identityProvider = config.option(AwsClientOption.TOKEN_IDENTITY_PROVIDER);
+ if (identityProvider != null) {
+ IdentityProviders identityProviders = config.option(SdkClientOption.IDENTITY_PROVIDERS);
+ builder.option(SdkClientOption.IDENTITY_PROVIDERS, identityProviders.toBuilder()
+ .putIdentityProvider(identityProvider).build());
+ }
+ builder.option(SdkClientOption.EXECUTION_INTERCEPTORS, interceptors).option(SdkClientOption.SERVICE_CONFIGURATION,
+ finalServiceConfig);
+ return builder.build();
+ }
+
+ @Override
+ protected final String signingName() {
+ return "json-service";
+ }
+
+ private JsonEndpointProvider defaultEndpointProvider() {
+ return JsonEndpointProvider.defaultProvider();
+ }
+
+ public B authSchemeProvider(JsonAuthSchemeProvider authSchemeProvider) {
+ clientConfiguration.option(SdkClientOption.AUTH_SCHEME_PROVIDER, authSchemeProvider);
+ return thisBuilder();
+ }
+
+ private JsonAuthSchemeProvider defaultAuthSchemeProvider() {
+ return JsonAuthSchemeProvider.defaultProvider();
+ }
+
+ @Override
+ public B putAuthScheme(AuthScheme> authScheme) {
+ additionalAuthSchemes.put(authScheme.schemeId(), authScheme);
+ return thisBuilder();
+ }
+
+ private Map> authSchemes() {
+ Map> schemes = new HashMap<>(3 + this.additionalAuthSchemes.size());
+ AwsV4AuthScheme awsV4AuthScheme = AwsV4AuthScheme.create();
+ schemes.put(awsV4AuthScheme.schemeId(), awsV4AuthScheme);
+ BearerAuthScheme bearerAuthScheme = BearerAuthScheme.create();
+ schemes.put(bearerAuthScheme.schemeId(), bearerAuthScheme);
+ NoAuthAuthScheme noAuthAuthScheme = NoAuthAuthScheme.create();
+ schemes.put(noAuthAuthScheme.schemeId(), noAuthAuthScheme);
+ schemes.putAll(this.additionalAuthSchemes);
+ return Collections.unmodifiableMap(schemes);
+ }
+
+ public B customParameter(Boolean customParameter) {
+ clientContextParams.put(JsonClientContextParams.CUSTOM_PARAMETER, customParameter);
+ return thisBuilder();
+ }
+
+ public B serviceConfiguration(ServiceConfiguration serviceConfiguration) {
+ clientConfiguration.option(SdkClientOption.SERVICE_CONFIGURATION, serviceConfiguration);
+ return thisBuilder();
+ }
+
+ public void setServiceConfiguration(ServiceConfiguration serviceConfiguration) {
+ serviceConfiguration(serviceConfiguration);
+ }
+
+ private IdentityProvider extends TokenIdentity> defaultTokenProvider() {
+ return DefaultAwsTokenProvider.create();
+ }
+
+ @Override
+ protected SdkClientConfiguration setOverrides(SdkClientConfiguration configuration) {
+ ClientOverrideConfiguration overrideConfiguration = overrideConfiguration();
+ if (overrideConfiguration == null) {
+ return configuration;
+ }
+ return SdkClientConfigurationUtil.copyOverridesToConfiguration(overrideConfiguration, configuration.toBuilder()).build();
+ }
+
+ @Override
+ protected SdkClientConfiguration invokePlugins(SdkClientConfiguration config) {
+ List plugins = plugins();
+ if (plugins.isEmpty()) {
+ return config;
+ }
+ JsonServiceClientConfigurationBuilder.BuilderInternal serviceConfigBuilder = JsonServiceClientConfigurationBuilder
+ .builder(config.toBuilder());
+ serviceConfigBuilder.overrideConfiguration(overrideConfiguration());
+ for (SdkPlugin plugin : plugins) {
+ plugin.configureClient(serviceConfigBuilder);
+ }
+ overrideConfiguration(serviceConfigBuilder.overrideConfiguration());
+ return serviceConfigBuilder.buildSdkClientConfiguration();
+ }
+
+ protected static void validateClientOptions(SdkClientConfiguration c) {
+ Validate.notNull(c.option(AwsClientOption.TOKEN_IDENTITY_PROVIDER),
+ "The 'tokenProvider' must be configured in the client builder.");
+ }
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-no-auth-ops-client-builder-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-no-auth-ops-client-builder-class.java
new file mode 100644
index 000000000000..25bcbb6adaaf
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-no-auth-ops-client-builder-class.java
@@ -0,0 +1,138 @@
+package software.amazon.awssdk.services.database;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import software.amazon.awssdk.annotations.Generated;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.awscore.client.builder.AwsDefaultClientBuilder;
+import software.amazon.awssdk.core.SdkPlugin;
+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.interceptor.ClasspathInterceptorChainFactory;
+import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
+import software.amazon.awssdk.http.auth.aws.scheme.AwsV4AuthScheme;
+import software.amazon.awssdk.http.auth.scheme.BearerAuthScheme;
+import software.amazon.awssdk.http.auth.scheme.NoAuthAuthScheme;
+import software.amazon.awssdk.http.auth.spi.scheme.AuthScheme;
+import software.amazon.awssdk.services.database.auth.scheme.DatabaseAuthSchemeProvider;
+import software.amazon.awssdk.services.database.auth.scheme.internal.DatabaseAuthSchemeInterceptor;
+import software.amazon.awssdk.services.database.endpoints.DatabaseEndpointProvider;
+import software.amazon.awssdk.services.database.endpoints.internal.DatabaseRequestSetEndpointInterceptor;
+import software.amazon.awssdk.services.database.endpoints.internal.DatabaseResolveEndpointInterceptor;
+import software.amazon.awssdk.services.database.internal.DatabaseServiceClientConfigurationBuilder;
+import software.amazon.awssdk.services.database.internal.SdkClientConfigurationUtil;
+import software.amazon.awssdk.utils.CollectionUtils;
+
+/**
+ * Internal base class for {@link DefaultDatabaseClientBuilder} and {@link DefaultDatabaseAsyncClientBuilder}.
+ */
+@Generated("software.amazon.awssdk:codegen")
+@SdkInternalApi
+abstract class DefaultDatabaseBaseClientBuilder, C> extends
+ AwsDefaultClientBuilder {
+ private final Map> additionalAuthSchemes = new HashMap<>();
+
+ @Override
+ protected final String serviceEndpointPrefix() {
+ return "database-service-endpoint";
+ }
+
+ @Override
+ protected final String serviceName() {
+ return "Database";
+ }
+
+ @Override
+ protected final SdkClientConfiguration mergeServiceDefaults(SdkClientConfiguration config) {
+ return config.merge(c -> c.option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
+ .option(SdkClientOption.AUTH_SCHEME_PROVIDER, defaultAuthSchemeProvider())
+ .option(SdkClientOption.AUTH_SCHEMES, authSchemes())
+ .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false));
+ }
+
+ @Override
+ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientConfiguration config) {
+ List endpointInterceptors = new ArrayList<>();
+ endpointInterceptors.add(new DatabaseAuthSchemeInterceptor());
+ endpointInterceptors.add(new DatabaseResolveEndpointInterceptor());
+ endpointInterceptors.add(new DatabaseRequestSetEndpointInterceptor());
+ ClasspathInterceptorChainFactory interceptorFactory = new ClasspathInterceptorChainFactory();
+ List interceptors = interceptorFactory
+ .getInterceptors("software/amazon/awssdk/services/database/execution.interceptors");
+ List additionalInterceptors = new ArrayList<>();
+ interceptors = CollectionUtils.mergeLists(endpointInterceptors, interceptors);
+ interceptors = CollectionUtils.mergeLists(interceptors, additionalInterceptors);
+ interceptors = CollectionUtils.mergeLists(interceptors, config.option(SdkClientOption.EXECUTION_INTERCEPTORS));
+ SdkClientConfiguration.Builder builder = config.toBuilder();
+ builder.option(SdkClientOption.EXECUTION_INTERCEPTORS, interceptors);
+ return builder.build();
+ }
+
+ @Override
+ protected final String signingName() {
+ return "database-service";
+ }
+
+ private DatabaseEndpointProvider defaultEndpointProvider() {
+ return DatabaseEndpointProvider.defaultProvider();
+ }
+
+ public B authSchemeProvider(DatabaseAuthSchemeProvider authSchemeProvider) {
+ clientConfiguration.option(SdkClientOption.AUTH_SCHEME_PROVIDER, authSchemeProvider);
+ return thisBuilder();
+ }
+
+ private DatabaseAuthSchemeProvider defaultAuthSchemeProvider() {
+ return DatabaseAuthSchemeProvider.defaultProvider();
+ }
+
+ @Override
+ public B putAuthScheme(AuthScheme> authScheme) {
+ additionalAuthSchemes.put(authScheme.schemeId(), authScheme);
+ return thisBuilder();
+ }
+
+ private Map> authSchemes() {
+ Map> schemes = new HashMap<>(3 + this.additionalAuthSchemes.size());
+ AwsV4AuthScheme awsV4AuthScheme = AwsV4AuthScheme.create();
+ schemes.put(awsV4AuthScheme.schemeId(), awsV4AuthScheme);
+ BearerAuthScheme bearerAuthScheme = BearerAuthScheme.create();
+ schemes.put(bearerAuthScheme.schemeId(), bearerAuthScheme);
+ NoAuthAuthScheme noAuthAuthScheme = NoAuthAuthScheme.create();
+ schemes.put(noAuthAuthScheme.schemeId(), noAuthAuthScheme);
+ schemes.putAll(this.additionalAuthSchemes);
+ return Collections.unmodifiableMap(schemes);
+ }
+
+ @Override
+ protected SdkClientConfiguration setOverrides(SdkClientConfiguration configuration) {
+ ClientOverrideConfiguration overrideConfiguration = overrideConfiguration();
+ if (overrideConfiguration == null) {
+ return configuration;
+ }
+ return SdkClientConfigurationUtil.copyOverridesToConfiguration(overrideConfiguration, configuration.toBuilder()).build();
+ }
+
+ @Override
+ protected SdkClientConfiguration invokePlugins(SdkClientConfiguration config) {
+ List plugins = plugins();
+ if (plugins.isEmpty()) {
+ return config;
+ }
+ DatabaseServiceClientConfigurationBuilder.BuilderInternal serviceConfigBuilder = DatabaseServiceClientConfigurationBuilder
+ .builder(config.toBuilder());
+ serviceConfigBuilder.overrideConfiguration(overrideConfiguration());
+ for (SdkPlugin plugin : plugins) {
+ plugin.configureClient(serviceConfigBuilder);
+ }
+ overrideConfiguration(serviceConfigBuilder.overrideConfiguration());
+ return serviceConfigBuilder.buildSdkClientConfiguration();
+ }
+
+ protected static void validateClientOptions(SdkClientConfiguration c) {
+ }
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-no-auth-service-client-builder-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-no-auth-service-client-builder-class.java
new file mode 100644
index 000000000000..516e0f2202a4
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-no-auth-service-client-builder-class.java
@@ -0,0 +1,132 @@
+package software.amazon.awssdk.services.database;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import software.amazon.awssdk.annotations.Generated;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.awscore.client.builder.AwsDefaultClientBuilder;
+import software.amazon.awssdk.core.SdkPlugin;
+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.interceptor.ClasspathInterceptorChainFactory;
+import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
+import software.amazon.awssdk.http.auth.scheme.NoAuthAuthScheme;
+import software.amazon.awssdk.http.auth.spi.scheme.AuthScheme;
+import software.amazon.awssdk.services.database.auth.scheme.DatabaseAuthSchemeProvider;
+import software.amazon.awssdk.services.database.auth.scheme.internal.DatabaseAuthSchemeInterceptor;
+import software.amazon.awssdk.services.database.endpoints.DatabaseEndpointProvider;
+import software.amazon.awssdk.services.database.endpoints.internal.DatabaseRequestSetEndpointInterceptor;
+import software.amazon.awssdk.services.database.endpoints.internal.DatabaseResolveEndpointInterceptor;
+import software.amazon.awssdk.services.database.internal.DatabaseServiceClientConfigurationBuilder;
+import software.amazon.awssdk.services.database.internal.SdkClientConfigurationUtil;
+import software.amazon.awssdk.utils.CollectionUtils;
+
+/**
+ * Internal base class for {@link DefaultDatabaseClientBuilder} and {@link DefaultDatabaseAsyncClientBuilder}.
+ */
+@Generated("software.amazon.awssdk:codegen")
+@SdkInternalApi
+abstract class DefaultDatabaseBaseClientBuilder, C> extends
+ AwsDefaultClientBuilder {
+ private final Map> additionalAuthSchemes = new HashMap<>();
+
+ @Override
+ protected final String serviceEndpointPrefix() {
+ return "database-service-endpoint";
+ }
+
+ @Override
+ protected final String serviceName() {
+ return "Database";
+ }
+
+ @Override
+ protected final SdkClientConfiguration mergeServiceDefaults(SdkClientConfiguration config) {
+ return config.merge(c -> c.option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
+ .option(SdkClientOption.AUTH_SCHEME_PROVIDER, defaultAuthSchemeProvider())
+ .option(SdkClientOption.AUTH_SCHEMES, authSchemes())
+ .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false));
+ }
+
+ @Override
+ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientConfiguration config) {
+ List endpointInterceptors = new ArrayList<>();
+ endpointInterceptors.add(new DatabaseAuthSchemeInterceptor());
+ endpointInterceptors.add(new DatabaseResolveEndpointInterceptor());
+ endpointInterceptors.add(new DatabaseRequestSetEndpointInterceptor());
+ ClasspathInterceptorChainFactory interceptorFactory = new ClasspathInterceptorChainFactory();
+ List interceptors = interceptorFactory
+ .getInterceptors("software/amazon/awssdk/services/database/execution.interceptors");
+ List additionalInterceptors = new ArrayList<>();
+ interceptors = CollectionUtils.mergeLists(endpointInterceptors, interceptors);
+ interceptors = CollectionUtils.mergeLists(interceptors, additionalInterceptors);
+ interceptors = CollectionUtils.mergeLists(interceptors, config.option(SdkClientOption.EXECUTION_INTERCEPTORS));
+ SdkClientConfiguration.Builder builder = config.toBuilder();
+ builder.option(SdkClientOption.EXECUTION_INTERCEPTORS, interceptors);
+ return builder.build();
+ }
+
+ @Override
+ protected final String signingName() {
+ return "database-service";
+ }
+
+ private DatabaseEndpointProvider defaultEndpointProvider() {
+ return DatabaseEndpointProvider.defaultProvider();
+ }
+
+ public B authSchemeProvider(DatabaseAuthSchemeProvider authSchemeProvider) {
+ clientConfiguration.option(SdkClientOption.AUTH_SCHEME_PROVIDER, authSchemeProvider);
+ return thisBuilder();
+ }
+
+ private DatabaseAuthSchemeProvider defaultAuthSchemeProvider() {
+ return DatabaseAuthSchemeProvider.defaultProvider();
+ }
+
+ @Override
+ public B putAuthScheme(AuthScheme> authScheme) {
+ additionalAuthSchemes.put(authScheme.schemeId(), authScheme);
+ return thisBuilder();
+ }
+
+ private Map> authSchemes() {
+ Map> schemes = new HashMap<>(1 + this.additionalAuthSchemes.size());
+ NoAuthAuthScheme noAuthAuthScheme = NoAuthAuthScheme.create();
+ schemes.put(noAuthAuthScheme.schemeId(), noAuthAuthScheme);
+ schemes.putAll(this.additionalAuthSchemes);
+ return Collections.unmodifiableMap(schemes);
+ }
+
+ @Override
+ protected SdkClientConfiguration setOverrides(SdkClientConfiguration configuration) {
+ ClientOverrideConfiguration overrideConfiguration = overrideConfiguration();
+ if (overrideConfiguration == null) {
+ return configuration;
+ }
+ return SdkClientConfigurationUtil.copyOverridesToConfiguration(overrideConfiguration, configuration.toBuilder()).build();
+ }
+
+ @Override
+ protected SdkClientConfiguration invokePlugins(SdkClientConfiguration config) {
+ List plugins = plugins();
+ if (plugins.isEmpty()) {
+ return config;
+ }
+ DatabaseServiceClientConfigurationBuilder.BuilderInternal serviceConfigBuilder = DatabaseServiceClientConfigurationBuilder
+ .builder(config.toBuilder());
+ serviceConfigBuilder.overrideConfiguration(overrideConfiguration());
+ for (SdkPlugin plugin : plugins) {
+ plugin.configureClient(serviceConfigBuilder);
+ }
+ overrideConfiguration(serviceConfigBuilder.overrideConfiguration());
+ return serviceConfigBuilder.buildSdkClientConfiguration();
+ }
+
+ protected static void validateClientOptions(SdkClientConfiguration c) {
+ }
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-query-client-builder-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-query-client-builder-class.java
new file mode 100644
index 000000000000..1b793ebbd783
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-query-client-builder-class.java
@@ -0,0 +1,171 @@
+package software.amazon.awssdk.services.query;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import software.amazon.awssdk.annotations.Generated;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.auth.token.credentials.aws.DefaultAwsTokenProvider;
+import software.amazon.awssdk.awscore.client.builder.AwsDefaultClientBuilder;
+import software.amazon.awssdk.awscore.client.config.AwsClientOption;
+import software.amazon.awssdk.core.SdkPlugin;
+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.interceptor.ClasspathInterceptorChainFactory;
+import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
+import software.amazon.awssdk.http.auth.aws.scheme.AwsV4AuthScheme;
+import software.amazon.awssdk.http.auth.scheme.BearerAuthScheme;
+import software.amazon.awssdk.http.auth.scheme.NoAuthAuthScheme;
+import software.amazon.awssdk.http.auth.spi.scheme.AuthScheme;
+import software.amazon.awssdk.identity.spi.IdentityProvider;
+import software.amazon.awssdk.identity.spi.IdentityProviders;
+import software.amazon.awssdk.identity.spi.TokenIdentity;
+import software.amazon.awssdk.protocols.query.interceptor.QueryParametersToBodyInterceptor;
+import software.amazon.awssdk.services.query.auth.scheme.QueryAuthSchemeProvider;
+import software.amazon.awssdk.services.query.auth.scheme.internal.QueryAuthSchemeInterceptor;
+import software.amazon.awssdk.services.query.endpoints.QueryClientContextParams;
+import software.amazon.awssdk.services.query.endpoints.QueryEndpointProvider;
+import software.amazon.awssdk.services.query.endpoints.internal.QueryRequestSetEndpointInterceptor;
+import software.amazon.awssdk.services.query.endpoints.internal.QueryResolveEndpointInterceptor;
+import software.amazon.awssdk.services.query.internal.QueryServiceClientConfigurationBuilder;
+import software.amazon.awssdk.services.query.internal.SdkClientConfigurationUtil;
+import software.amazon.awssdk.utils.CollectionUtils;
+import software.amazon.awssdk.utils.Validate;
+
+/**
+ * Internal base class for {@link DefaultQueryClientBuilder} and {@link DefaultQueryAsyncClientBuilder}.
+ */
+@Generated("software.amazon.awssdk:codegen")
+@SdkInternalApi
+abstract class DefaultQueryBaseClientBuilder