diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/AddMetadata.java b/codegen/src/main/java/software/amazon/awssdk/codegen/AddMetadata.java index 7442ae662324..d84e5ade4788 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/AddMetadata.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/AddMetadata.java @@ -59,6 +59,7 @@ public static Metadata constructMetadata(ServiceModel serviceModel, .withPaginatorsPackageName(namingStrategy.getPaginatorsPackageName(serviceName)) .withWaitersPackageName(namingStrategy.getWaitersPackageName(serviceName)) .withEndpointRulesPackageName(namingStrategy.getEndpointRulesPackageName(serviceName)) + .withAuthSchemePackageName(namingStrategy.getAuthSchemePackageName(serviceName)) .withServiceAbbreviation(serviceMetadata.getServiceAbbreviation()) .withServiceFullName(serviceMetadata.getServiceFullName()) .withServiceName(serviceName) diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/GeneratorPathProvider.java b/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/GeneratorPathProvider.java index 5e680b97b320..8cc7b1f36026 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/GeneratorPathProvider.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/GeneratorPathProvider.java @@ -95,4 +95,13 @@ public String getEndpointRulesInternalResourcesDirectory() { public String getEndpointRulesTestDirectory() { return testDirectory + "/" + Utils.packageToDirectory(model.getMetadata().getFullEndpointRulesPackageName()); } + + public String getAuthSchemeDirectory() { + return sourceDirectory + "/" + Utils.packageToDirectory(model.getMetadata().getFullAuthSchemePackageName()); + } + + public String getAuthSchemeInternalDirectory() { + return sourceDirectory + "/" + Utils.packageToDirectory(model.getMetadata().getFullInternalAuthSchemePackageName()); + } + } diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/AuthSchemeGeneratorTasks.java b/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/AuthSchemeGeneratorTasks.java new file mode 100644 index 000000000000..eaff0a1bd10c --- /dev/null +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/AuthSchemeGeneratorTasks.java @@ -0,0 +1,69 @@ +/* + * 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.emitters.tasks; + +import java.util.ArrayList; +import java.util.List; +import software.amazon.awssdk.codegen.emitters.GeneratorTask; +import software.amazon.awssdk.codegen.emitters.GeneratorTaskParams; +import software.amazon.awssdk.codegen.emitters.PoetGeneratorTask; +import software.amazon.awssdk.codegen.poet.auth.scheme.AuthSchemeParamsSpec; +import software.amazon.awssdk.codegen.poet.auth.scheme.AuthSchemeProviderSpec; +import software.amazon.awssdk.codegen.poet.auth.scheme.DefaultAuthSchemeParamsSpec; +import software.amazon.awssdk.codegen.poet.auth.scheme.DefaultAuthSchemeProviderSpec; + +public final class AuthSchemeGeneratorTasks extends BaseGeneratorTasks { + private final GeneratorTaskParams generatorTaskParams; + + public AuthSchemeGeneratorTasks(GeneratorTaskParams dependencies) { + super(dependencies); + this.generatorTaskParams = dependencies; + } + + @Override + protected List createTasks() throws Exception { + List tasks = new ArrayList<>(); + tasks.add(generateParamsInterface()); + tasks.add(generateProviderInterface()); + tasks.add(generateDefaultParamsImpl()); + tasks.add(generateDefaultProviderImpl()); + return tasks; + } + + private GeneratorTask generateParamsInterface() { + return new PoetGeneratorTask(authSchemeDir(), model.getFileHeader(), new AuthSchemeParamsSpec(model)); + } + + private GeneratorTask generateDefaultParamsImpl() { + return new PoetGeneratorTask(authSchemeInternalDir(), model.getFileHeader(), new DefaultAuthSchemeParamsSpec(model)); + } + + private GeneratorTask generateProviderInterface() { + return new PoetGeneratorTask(authSchemeDir(), model.getFileHeader(), new AuthSchemeProviderSpec(model)); + } + + private GeneratorTask generateDefaultProviderImpl() { + return new PoetGeneratorTask(authSchemeInternalDir(), model.getFileHeader(), new DefaultAuthSchemeProviderSpec(model)); + } + + private String authSchemeDir() { + return generatorTaskParams.getPathProvider().getAuthSchemeDirectory(); + } + + private String authSchemeInternalDir() { + return generatorTaskParams.getPathProvider().getAuthSchemeInternalDirectory(); + } +} diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/AwsGeneratorTasks.java b/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/AwsGeneratorTasks.java index 197b35f9effa..a6b3b75e4fcc 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/AwsGeneratorTasks.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/AwsGeneratorTasks.java @@ -27,6 +27,7 @@ public AwsGeneratorTasks(GeneratorTaskParams params) { new PaginatorsGeneratorTasks(params), new EventStreamGeneratorTasks(params), new WaitersGeneratorTasks(params), - new EndpointProviderTasks(params)); + new EndpointProviderTasks(params), + new AuthSchemeGeneratorTasks(params)); } } diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/internal/Constant.java b/codegen/src/main/java/software/amazon/awssdk/codegen/internal/Constant.java index 538fd383782a..3b59808a594a 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/internal/Constant.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/internal/Constant.java @@ -70,6 +70,9 @@ public final class Constant { public static final String PACKAGE_NAME_RULES_PATTERN = "%s.endpoints"; + // TODO: reviewer: maybe just auth instead of authscheme? or auth.scheme? + public static final String PACKAGE_NAME_AUTH_SCHEME_PATTERN = "%s.auth.scheme"; + public static final String PACKAGE_NAME_SMOKE_TEST_PATTERN = "%s.smoketests"; public static final String PACKAGE_NAME_CUSTOM_AUTH_PATTERN = "%s.auth"; diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/Metadata.java b/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/Metadata.java index 1803ef245d6c..8cff0c0e8db3 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/Metadata.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/Metadata.java @@ -72,6 +72,8 @@ public class Metadata { private String endpointRulesPackageName; + private String authSchemePackageName; + private String serviceAbbreviation; private String serviceFullName; @@ -723,6 +725,27 @@ public String getFullInternalEndpointRulesPackageName() { return joinPackageNames(getFullEndpointRulesPackageName(), "internal"); } + public void setAuthSchemePackageName(String authSchemePackageName) { + this.authSchemePackageName = authSchemePackageName; + } + + public Metadata withAuthSchemePackageName(String authSchemePackageName) { + setAuthSchemePackageName(authSchemePackageName); + return this; + } + + public String getAuthSchemePackageName() { + return authSchemePackageName; + } + + public String getFullAuthSchemePackageName() { + return joinPackageNames(rootPackageName, getAuthSchemePackageName()); + } + + public String getFullInternalAuthSchemePackageName() { + return joinPackageNames(getFullAuthSchemePackageName(), "internal"); + } + public String getFullInternalPackageName() { return joinPackageNames(getFullClientPackageName(), "internal"); } diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/naming/DefaultNamingStrategy.java b/codegen/src/main/java/software/amazon/awssdk/codegen/naming/DefaultNamingStrategy.java index f764525e67f9..03f718a8c1f4 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/naming/DefaultNamingStrategy.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/naming/DefaultNamingStrategy.java @@ -179,6 +179,11 @@ public String getEndpointRulesPackageName(String serviceName) { return getCustomizedPackageName(concatServiceNameIfShareModel(serviceName), Constant.PACKAGE_NAME_RULES_PATTERN); } + @Override + public String getAuthSchemePackageName(String serviceName) { + return getCustomizedPackageName(concatServiceNameIfShareModel(serviceName), Constant.PACKAGE_NAME_AUTH_SCHEME_PATTERN); + } + @Override public String getSmokeTestPackageName(String serviceName) { diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/naming/NamingStrategy.java b/codegen/src/main/java/software/amazon/awssdk/codegen/naming/NamingStrategy.java index 5563e760af3f..f231062c14bf 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/naming/NamingStrategy.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/naming/NamingStrategy.java @@ -18,6 +18,7 @@ import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel; import software.amazon.awssdk.codegen.model.intermediate.MemberModel; import software.amazon.awssdk.codegen.model.service.Shape; +import software.amazon.awssdk.core.SdkField; /** * Strategy to name various Java constructs based on the naming in the model and potentially customizations. @@ -63,6 +64,11 @@ public interface NamingStrategy { */ String getEndpointRulesPackageName(String serviceName); + /** + * Retrieve the auth scheme package name that should be used based on the service name. + */ + String getAuthSchemePackageName(String serviceName); + /** * Retrieve the smote test package name that should be used based on the service name. */ diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeParamsSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeParamsSpec.java new file mode 100644 index 000000000000..ec43d09f75b5 --- /dev/null +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeParamsSpec.java @@ -0,0 +1,130 @@ +/* + * 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 com.squareup.javapoet.ClassName; +import com.squareup.javapoet.CodeBlock; +import com.squareup.javapoet.MethodSpec; +import com.squareup.javapoet.ParameterSpec; +import com.squareup.javapoet.ParameterizedTypeName; +import com.squareup.javapoet.TypeSpec; +import java.util.Optional; +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.poet.ClassSpec; +import software.amazon.awssdk.codegen.poet.PoetUtils; + +public class AuthSchemeParamsSpec implements ClassSpec { + private final IntermediateModel intermediateModel; + private final AuthSchemeSpecUtils authSchemeSpecUtils; + + public AuthSchemeParamsSpec(IntermediateModel intermediateModel) { + this.intermediateModel = intermediateModel; + this.authSchemeSpecUtils = new AuthSchemeSpecUtils(intermediateModel); + } + + @Override + public ClassName className() { + return authSchemeSpecUtils.parametersInterfaceName(); + } + + @Override + public TypeSpec poetSpec() { + TypeSpec.Builder b = PoetUtils.createInterfaceBuilder(className()) + .addModifiers(Modifier.PUBLIC) + .addAnnotation(SdkPublicApi.class) + .addJavadoc(interfaceJavadoc()) + .addMethod(builderMethod()) + .addType(builderInterfaceSpec()); + + addAccessorMethods(b); + return b.build(); + } + + private CodeBlock interfaceJavadoc() { + CodeBlock.Builder b = CodeBlock.builder(); + + b.add("The parameters object used to resolve the auth schemes for the $N service.", + intermediateModel.getMetadata().getServiceName()); + + return b.build(); + } + + private MethodSpec builderMethod() { + return MethodSpec.methodBuilder("builder") + .addModifiers(Modifier.PUBLIC, Modifier.STATIC) + .returns(authSchemeSpecUtils.parametersInterfaceBuilderInterfaceName()) + .addStatement("return $T.builder()", authSchemeSpecUtils.parametersDefaultImplName()) + .addJavadoc("Get a new builder for creating a {@link $T}.", + authSchemeSpecUtils.parametersInterfaceName()) + .build(); + } + + private TypeSpec builderInterfaceSpec() { + TypeSpec.Builder b = TypeSpec.interfaceBuilder(authSchemeSpecUtils.parametersInterfaceBuilderInterfaceName()) + .addModifiers(Modifier.PUBLIC, Modifier.STATIC) + .addJavadoc("A builder for a {@link $T}.", authSchemeSpecUtils.parametersInterfaceName()); + + addBuilderSetterMethods(b); + + b.addMethod(MethodSpec.methodBuilder("build") + .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT) + .returns(className()) + .addJavadoc("Returns a {@link $T} object that is created from the properties that have been set " + + "on the builder.", authSchemeSpecUtils.parametersInterfaceName()) + .build()); + + return b.build(); + } + + private void addAccessorMethods(TypeSpec.Builder b) { + b.addMethod(MethodSpec.methodBuilder("operation") + .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT) + .returns(String.class) + .addJavadoc("Returns the operation for which to resolve the auth scheme.") + .build()); + + if (authSchemeSpecUtils.usesSigV4()) { + b.addMethod(MethodSpec.methodBuilder("region") + .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT) + // TODO: Should region be Regions? (Regions.class isn't available here though) + .returns(ParameterizedTypeName.get(Optional.class, String.class)) + .addJavadoc("Returns the region. The region is optional. The region parameter may be used " + + "with $S auth scheme. By default, the region will be empty.", "aws.auth#sigv4") + .build()); + } + } + + private void addBuilderSetterMethods(TypeSpec.Builder b) { + b.addMethod(MethodSpec.methodBuilder("operation") + .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT) + .addParameter(ParameterSpec.builder(String.class, "operation").build()) + .returns(authSchemeSpecUtils.parametersInterfaceBuilderInterfaceName()) + .addJavadoc("Set the operation for which to resolve the auth scheme.") + .build()); + + if (authSchemeSpecUtils.usesSigV4()) { + b.addMethod(MethodSpec.methodBuilder("region") + .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT) + .addParameter(ParameterSpec.builder(String.class, "region").build()) + .returns(authSchemeSpecUtils.parametersInterfaceBuilderInterfaceName()) + .addJavadoc("Set the region. The region parameter may be used with the $S auth scheme.", + "aws.auth#sigv4") // TODO: Reference the SigV4 AuthScheme when implemented + .build()); + } + } +} diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeProviderSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeProviderSpec.java new file mode 100644 index 000000000000..11d38010b696 --- /dev/null +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeProviderSpec.java @@ -0,0 +1,115 @@ +/* + * 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 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 java.util.function.Consumer; +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.poet.ClassSpec; +import software.amazon.awssdk.codegen.poet.PoetUtils; +import software.amazon.awssdk.http.auth.spi.AuthSchemeProvider; +import software.amazon.awssdk.http.auth.spi.HttpAuthOption; + +public class AuthSchemeProviderSpec implements ClassSpec { + private final IntermediateModel intermediateModel; + private final AuthSchemeSpecUtils authSchemeSpecUtils; + + public AuthSchemeProviderSpec(IntermediateModel intermediateModel) { + this.intermediateModel = intermediateModel; + this.authSchemeSpecUtils = new AuthSchemeSpecUtils(intermediateModel); + } + + @Override + public ClassName className() { + return authSchemeSpecUtils.providerInterfaceName(); + } + + @Override + public TypeSpec poetSpec() { + return PoetUtils.createInterfaceBuilder(className()) + .addSuperinterface(AuthSchemeProvider.class) + .addModifiers(Modifier.PUBLIC) + .addAnnotation(SdkPublicApi.class) + .addJavadoc(interfaceJavadoc()) + .addMethod(resolveAuthSchemeMethod()) + .addMethod(resolveAuthSchemeConsumerBuilderMethod()) + .addMethod(defaultProviderMethod()) + .build(); + } + + private MethodSpec resolveAuthSchemeMethod() { + MethodSpec.Builder b = MethodSpec.methodBuilder("resolveAuthScheme"); + b.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT); + b.addParameter(authSchemeSpecUtils.parametersInterfaceName(), "authSchemeParams"); + b.returns(authSchemeSpecUtils.resolverReturnType()); + b.addJavadoc(resolveMethodJavadoc()); + return b.build(); + } + + private MethodSpec resolveAuthSchemeConsumerBuilderMethod() { + ClassName parametersInterface = authSchemeSpecUtils.parametersInterfaceName(); + ClassName parametersBuilderInterface = parametersInterface.nestedClass("Builder"); + TypeName consumerType = ParameterizedTypeName.get(ClassName.get(Consumer.class), parametersBuilderInterface); + + MethodSpec.Builder b = MethodSpec.methodBuilder("resolveAuthScheme"); + b.addModifiers(Modifier.PUBLIC, Modifier.DEFAULT); + b.addParameter(consumerType, "consumer"); + b.returns(authSchemeSpecUtils.resolverReturnType()); + b.addJavadoc(resolveMethodJavadoc()); + + b.addStatement("$T builder = $T.builder()", parametersBuilderInterface, parametersInterface); + b.addStatement("consumer.accept(builder)"); + b.addStatement("return resolveAuthScheme(builder.build())"); + + return b.build(); + } + + private MethodSpec defaultProviderMethod() { + return MethodSpec.methodBuilder("defaultProvider") + .addModifiers(Modifier.PUBLIC, Modifier.STATIC) + .returns(className()) + .addJavadoc("Get the default auth scheme provider.") + .addStatement("return $T.create()", authSchemeSpecUtils.providerDefaultImplName()) + .build(); + } + + private CodeBlock interfaceJavadoc() { + CodeBlock.Builder b = CodeBlock.builder(); + + b.add("An auth scheme provider for $N service. The auth scheme provider takes a set of parameters using {@link $T}, and " + + "resolves a list of {@link $T} based on the given parameters.", + intermediateModel.getMetadata().getServiceName(), + authSchemeSpecUtils.parametersInterfaceName(), + HttpAuthOption.class); + + return b.build(); + } + + private CodeBlock resolveMethodJavadoc() { + CodeBlock.Builder b = CodeBlock.builder(); + + b.add("Resolve the auth schemes based on the given set of parameters."); + + return b.build(); + } +} diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeSpecUtils.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeSpecUtils.java new file mode 100644 index 000000000000..edafa4f734a4 --- /dev/null +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeSpecUtils.java @@ -0,0 +1,69 @@ +/* + * 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 com.squareup.javapoet.ClassName; +import com.squareup.javapoet.ParameterizedTypeName; +import com.squareup.javapoet.TypeName; +import java.util.List; +import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel; +import software.amazon.awssdk.codegen.utils.AuthUtils; +import software.amazon.awssdk.http.auth.spi.HttpAuthOption; + +final class AuthSchemeSpecUtils { + private final IntermediateModel intermediateModel; + + AuthSchemeSpecUtils(IntermediateModel intermediateModel) { + this.intermediateModel = intermediateModel; + } + + private String basePackage() { + return intermediateModel.getMetadata().getFullAuthSchemePackageName(); + } + + private String internalPackage() { + return intermediateModel.getMetadata().getFullInternalAuthSchemePackageName(); + } + + public ClassName parametersInterfaceName() { + return ClassName.get(basePackage(), intermediateModel.getMetadata().getServiceName() + "AuthSchemeParams"); + } + + public ClassName parametersInterfaceBuilderInterfaceName() { + return parametersInterfaceName().nestedClass("Builder"); + } + + public ClassName parametersDefaultImplName() { + return ClassName.get(internalPackage(), "Default" + parametersInterfaceName().simpleName()); + } + + public ClassName providerInterfaceName() { + return ClassName.get(basePackage(), intermediateModel.getMetadata().getServiceName() + "AuthSchemeProvider"); + } + + public ClassName providerDefaultImplName() { + return ClassName.get(internalPackage(), "Default" + providerInterfaceName().simpleName()); + } + + public TypeName resolverReturnType() { + return ParameterizedTypeName.get(List.class, HttpAuthOption.class); + } + + public boolean usesSigV4() { + return AuthUtils.usesAwsAuth(intermediateModel); + } + +} diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/DefaultAuthSchemeParamsSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/DefaultAuthSchemeParamsSpec.java new file mode 100644 index 000000000000..348fc99ef408 --- /dev/null +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/DefaultAuthSchemeParamsSpec.java @@ -0,0 +1,152 @@ +/* + * 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 com.squareup.javapoet.ClassName; +import com.squareup.javapoet.FieldSpec; +import com.squareup.javapoet.MethodSpec; +import com.squareup.javapoet.ParameterSpec; +import com.squareup.javapoet.ParameterizedTypeName; +import com.squareup.javapoet.TypeSpec; +import java.lang.reflect.Type; +import java.util.Optional; +import javax.lang.model.element.Modifier; +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.utils.Validate; + +public class DefaultAuthSchemeParamsSpec implements ClassSpec { + private final AuthSchemeSpecUtils authSchemeSpecUtils; + + public DefaultAuthSchemeParamsSpec(IntermediateModel intermediateModel) { + this.authSchemeSpecUtils = new AuthSchemeSpecUtils(intermediateModel); + } + + @Override + public ClassName className() { + return authSchemeSpecUtils.parametersDefaultImplName(); + } + + @Override + public TypeSpec poetSpec() { + TypeSpec.Builder b = PoetUtils.createClassBuilder(className()) + .addModifiers(Modifier.PUBLIC, Modifier.FINAL) + .addAnnotation(SdkInternalApi.class) + .addSuperinterface(authSchemeSpecUtils.parametersInterfaceName()) + .addMethod(constructor()) + .addMethod(builderMethod()) + .addType(builderImplSpec()); + + addFieldsAndAccessors(b); + + return b.build(); + } + + private MethodSpec constructor() { + MethodSpec.Builder b = MethodSpec.constructorBuilder() + .addModifiers(Modifier.PRIVATE) + .addParameter(builderClassName(), "builder") + .addStatement("this.operation = $T.paramNotNull(builder.operation, \"operation\")", + Validate.class); + + if (authSchemeSpecUtils.usesSigV4()) { + b.addStatement("this.region = builder.region"); + } + return b.build(); + } + + private MethodSpec builderMethod() { + return MethodSpec.methodBuilder("builder") + .addModifiers(Modifier.PUBLIC, Modifier.STATIC) + .returns(authSchemeSpecUtils.parametersInterfaceBuilderInterfaceName()) + .addStatement("return new $T()", builderClassName()) + .build(); + } + + private TypeSpec builderImplSpec() { + TypeSpec.Builder b = TypeSpec.classBuilder(builderClassName()) + .addModifiers(Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL) + .addSuperinterface(authSchemeSpecUtils.parametersInterfaceBuilderInterfaceName()); + + addBuilderFieldsAndSetter(b); + + b.addMethod(MethodSpec.methodBuilder("build") + .addModifiers(Modifier.PUBLIC) + .addAnnotation(Override.class) + .returns(authSchemeSpecUtils.parametersInterfaceName()) + .addStatement("return new $T(this)", className()) + .build()); + + return b.build(); + } + + private void addFieldsAndAccessors(TypeSpec.Builder b) { + b.addField(FieldSpec.builder(String.class, "operation") + .addModifiers(Modifier.PRIVATE, Modifier.FINAL) + .build()); + + b.addMethod(MethodSpec.methodBuilder("operation") + .addModifiers(Modifier.PUBLIC) + .addAnnotation(Override.class) + .returns(String.class) + .addStatement("return operation") + .build()); + + if (authSchemeSpecUtils.usesSigV4()) { + b.addField(FieldSpec.builder(String.class, "region") + .addModifiers(Modifier.PRIVATE, Modifier.FINAL) + .build()); + + b.addMethod(MethodSpec.methodBuilder("region") + .addModifiers(Modifier.PUBLIC) + .addAnnotation(Override.class) + .returns(ParameterizedTypeName.get(Optional.class, String.class)) + .addStatement("return region == null ? Optional.empty() : Optional.of(region)") + .build()); + } + } + + private void addBuilderFieldsAndSetter(TypeSpec.Builder b) { + b.addField(FieldSpec.builder(String.class, "operation") + .addModifiers(Modifier.PRIVATE) + .build()); + b.addMethod(builderSetterMethod("operation", String.class)); + + if (authSchemeSpecUtils.usesSigV4()) { + b.addField(FieldSpec.builder(String.class, "region") + .addModifiers(Modifier.PRIVATE) + .build()); + b.addMethod(builderSetterMethod("region", String.class)); + } + } + + private MethodSpec builderSetterMethod(String field, Type type) { + return MethodSpec.methodBuilder(field) + .addModifiers(Modifier.PUBLIC) + .addAnnotation(Override.class) + .addParameter(ParameterSpec.builder(type, field).build()) + .returns(builderClassName()) + .addStatement("this.$L = $L", field, field) + .addStatement("return this") + .build(); + } + + private ClassName builderClassName() { + return className().nestedClass("Builder"); + } +} diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/DefaultAuthSchemeProviderSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/DefaultAuthSchemeProviderSpec.java new file mode 100644 index 000000000000..fb6e48a17e77 --- /dev/null +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/DefaultAuthSchemeProviderSpec.java @@ -0,0 +1,83 @@ +/* + * 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 com.squareup.javapoet.ClassName; +import com.squareup.javapoet.FieldSpec; +import com.squareup.javapoet.MethodSpec; +import com.squareup.javapoet.TypeSpec; +import java.util.ArrayList; +import javax.lang.model.element.Modifier; +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; + +public class DefaultAuthSchemeProviderSpec implements ClassSpec { + private final AuthSchemeSpecUtils authSchemeSpecUtils; + + public DefaultAuthSchemeProviderSpec(IntermediateModel intermediateModel) { + this.authSchemeSpecUtils = new AuthSchemeSpecUtils(intermediateModel); + } + + @Override + public ClassName className() { + return authSchemeSpecUtils.providerDefaultImplName(); + } + + @Override + public TypeSpec poetSpec() { + return PoetUtils.createClassBuilder(className()) + .addModifiers(Modifier.PUBLIC, Modifier.FINAL) + .addAnnotation(SdkInternalApi.class) + .addSuperinterface(authSchemeSpecUtils.providerInterfaceName()) + .addMethod(constructor()) + .addField(defaultInstance()) + .addMethod(createMethod()) + .addMethod(resolveAuthSchemeMethod()) + .build(); + } + + private FieldSpec defaultInstance() { + return FieldSpec.builder(className(), "DEFAULT") + .addModifiers(Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL) + .initializer("new $T()", className()) + .build(); + } + + private MethodSpec constructor() { + return MethodSpec.constructorBuilder().addModifiers(Modifier.PRIVATE).build(); + } + + private MethodSpec createMethod() { + return MethodSpec.methodBuilder("create") + .addModifiers(Modifier.PUBLIC, Modifier.STATIC) + .returns(className()) + .addStatement("return DEFAULT") + .build(); + } + + private MethodSpec resolveAuthSchemeMethod() { + return MethodSpec.methodBuilder("resolveAuthScheme") + .addModifiers(Modifier.PUBLIC) + .addAnnotation(Override.class) + .returns(authSchemeSpecUtils.resolverReturnType()) + .addParameter(authSchemeSpecUtils.parametersInterfaceName(), "authSchemeParams") + // TODO: make real implementation + .addStatement("return new $T<>()", ArrayList.class) + .build(); + } +} 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..ab98b57fc30e --- /dev/null +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeSpecTest.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.codegen.poet.auth.scheme; + +import static org.hamcrest.MatcherAssert.assertThat; +import static software.amazon.awssdk.codegen.poet.PoetMatchers.generatesTo; + +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.codegen.poet.ClassSpec; +import software.amazon.awssdk.codegen.poet.ClientTestModels; + +public class AuthSchemeSpecTest { + + @Test + public void authSchemeParams() { + ClassSpec authSchemeParams = new AuthSchemeParamsSpec(ClientTestModels.queryServiceModels()); + assertThat(authSchemeParams, generatesTo("auth-scheme-params.java")); + } + + @Test + public void authSchemeProvider() { + ClassSpec authSchemeProvider = new AuthSchemeProviderSpec(ClientTestModels.queryServiceModels()); + assertThat(authSchemeProvider, generatesTo("auth-scheme-provider.java")); + } + + @Test + public void defaultAuthSchemeParams() { + ClassSpec defaultAuthSchemeParams = new DefaultAuthSchemeParamsSpec(ClientTestModels.queryServiceModels()); + assertThat(defaultAuthSchemeParams, generatesTo("default-auth-scheme-params.java")); + } + + @Test + public void defaultAuthSchemeProvider() { + ClassSpec defaultAuthSchemeProvider = new DefaultAuthSchemeProviderSpec(ClientTestModels.queryServiceModels()); + assertThat(defaultAuthSchemeProvider, generatesTo("default-auth-scheme-provider.java")); + } +} 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..3e13b9e21128 --- /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.AuthSchemeProvider; +import software.amazon.awssdk.http.auth.spi.HttpAuthOption; +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 HttpAuthOption} 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/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..e0cecbe054b1 --- /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.HttpAuthOption; +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/core/auth/pom.xml b/core/auth/pom.xml index 13db25646058..cc87b1f54b53 100644 --- a/core/auth/pom.xml +++ b/core/auth/pom.xml @@ -53,6 +53,11 @@ identity-spi ${awsjavasdk.version} + + software.amazon.awssdk + http-auth + ${awsjavasdk.version} + software.amazon.awssdk regions diff --git a/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/AuthSchemeProvider.java b/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/AuthSchemeProvider.java new file mode 100644 index 000000000000..8db58fac1da3 --- /dev/null +++ b/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/AuthSchemeProvider.java @@ -0,0 +1,26 @@ +/* + * 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.http.auth.spi; + +import software.amazon.awssdk.annotations.SdkPublicApi; + +/** + * A marker interface for an auth scheme provider. An auth scheme provider takes as input a set of service-specific parameters, + * and resolves a list of {@link HttpAuthOption} based on the given parameters. + */ +@SdkPublicApi +public interface AuthSchemeProvider { +}