private MethodSpec finalizeServiceConfigurationMethod()

in codegen/src/main/java/software/amazon/awssdk/codegen/poet/builder/BaseClientBuilderClass.java [336:533]


    private MethodSpec finalizeServiceConfigurationMethod() {
        String requestHandlerDirectory = Utils.packageToDirectory(model.getMetadata().getFullClientPackageName());
        String requestHandlerPath = String.format("%s/execution.interceptors", requestHandlerDirectory);

        MethodSpec.Builder builder = MethodSpec.methodBuilder("finalizeServiceConfiguration")
                                               .addAnnotation(Override.class)
                                               .addModifiers(PROTECTED, FINAL)
                                               .returns(SdkClientConfiguration.class)
                                               .addParameter(SdkClientConfiguration.class, "config");

        // Initialize configuration values

        builder.addStatement("$T endpointInterceptors = new $T<>()",
                             ParameterizedTypeName.get(List.class, ExecutionInterceptor.class),
                             ArrayList.class);

        List<ClassName> builtInInterceptors = new ArrayList<>();

        if (authSchemeSpecUtils.useSraAuth()) {
            builtInInterceptors.add(authSchemeSpecUtils.authSchemeInterceptor());
        }
        builtInInterceptors.add(endpointRulesSpecUtils.resolverInterceptorName());
        builtInInterceptors.add(endpointRulesSpecUtils.requestModifierInterceptorName());

        for (String interceptor : model.getCustomizationConfig().getInterceptors()) {
            builtInInterceptors.add(ClassName.bestGuess(interceptor));
        }

        for (ClassName interceptor : builtInInterceptors) {
            builder.addStatement("endpointInterceptors.add(new $T())", interceptor);
        }


        builder.addCode("$1T interceptorFactory = new $1T();\n", ClasspathInterceptorChainFactory.class)
               .addCode("$T<$T> interceptors = interceptorFactory.getInterceptors($S);\n",
                        List.class, ExecutionInterceptor.class, requestHandlerPath);

        builder.addStatement("$T additionalInterceptors = new $T<>()",
                             ParameterizedTypeName.get(List.class,
                                                       ExecutionInterceptor.class),
                             ArrayList.class);

        builder.addStatement("interceptors = $T.mergeLists(endpointInterceptors, interceptors)",
                             CollectionUtils.class);
        builder.addStatement("interceptors = $T.mergeLists(interceptors, additionalInterceptors)",
                             CollectionUtils.class);

        builder.addCode("interceptors = $T.mergeLists(interceptors, config.option($T.EXECUTION_INTERCEPTORS));\n",
                        CollectionUtils.class, SdkClientOption.class);
        if (model.getEndpointOperation().isPresent()) {
            builder.beginControlFlow("if (!endpointDiscoveryEnabled)")
                   .addStatement("$1T chain = new $1T(config)", DefaultEndpointDiscoveryProviderChain.class)
                   .addStatement("endpointDiscoveryEnabled = chain.resolveEndpointDiscovery()")
                   .endControlFlow();
        }

        String clientConfigClassName = model.getCustomizationConfig().getServiceConfig().getClassName();
        if (StringUtils.isNotBlank(clientConfigClassName)) {
            mergeServiceConfiguration(builder, clientConfigClassName);
        }

        if (model.getCustomizationConfig().useGlobalEndpoint()) {
            builder.addStatement("$1T globalEndpointResolver = new $1T(config)",
                                 ClassName.get("software.amazon.awssdk.services.s3.internal.endpoints",
                                               "UseGlobalEndpointResolver"));
        }

        if (model.getCustomizationConfig().useS3ExpressSessionAuth()) {
            builder.addStatement("$1T useS3ExpressAuthResolver = new $1T(config)",
                                 ClassName.get("software.amazon.awssdk.services.s3.internal.s3express",
                                               "UseS3ExpressAuthResolver"));

            CodeBlock key = CodeBlock.of("$T.DISABLE_S3_EXPRESS_SESSION_AUTH",
                                         endpointRulesSpecUtils.clientContextParamsName());
            builder.beginControlFlow("if (clientContextParams.get($L) == null)",
                                     key);
            builder.addStatement("clientContextParams.put($L, !useS3ExpressAuthResolver.resolve())", key);
            builder.endControlFlow();
        }

        // Update configuration
        builder.addStatement("$T builder = config.toBuilder()", SdkClientConfiguration.Builder.class);
        builder.addCode("builder.lazyOption($T.IDENTITY_PROVIDERS, c -> {", SdkClientOption.class)
               .addStatement("$1T.Builder result = $1T.builder()", IdentityProviders.class);
        if (AuthUtils.usesBearerAuth(model)) {
            builder.addStatement("$T<?> tokenIdentityProvider = c.get($T.TOKEN_IDENTITY_PROVIDER)",
                                 IdentityProvider.class, AwsClientOption.class);
            builder.beginControlFlow("if (tokenIdentityProvider != null)");
            builder.addStatement("result.putIdentityProvider(tokenIdentityProvider)");
            builder.endControlFlow();
        }
        if (AuthUtils.usesAwsAuth(model)) {
            builder.addStatement("$T<?> credentialsIdentityProvider = c.get($T.CREDENTIALS_IDENTITY_PROVIDER)",
                                 IdentityProvider.class, AwsClientOption.class);
            builder.beginControlFlow("if (credentialsIdentityProvider != null)", AwsClientOption.class);
            builder.addStatement("result.putIdentityProvider(credentialsIdentityProvider)");
            builder.endControlFlow();
        }
        builder.addStatement("return result.build()")
               .addCode("});");

        builder.addStatement("builder.option($1T.EXECUTION_INTERCEPTORS, interceptors)", SdkClientOption.class);

        if (model.getCustomizationConfig().getServiceConfig().hasDualstackProperty()) {
            // NOTE: usage of serviceConfigBuilder and not finalServiceConfig is intentional. We need the nullable boolean here
            // to ensure fallback resolution of the dualstack configuration if dualstack was not explicitly configured on
            // serviceConfigBuilder; the service configuration classes (e.g. S3Configuration) return primitive booleans that
            // have a default when not present.
            builder.addStatement("builder.option($T.DUALSTACK_ENDPOINT_ENABLED, serviceConfigBuilder.dualstackEnabled())",
                            AwsClientOption.class);
        }

        if (model.getCustomizationConfig().getServiceConfig().hasFipsProperty()) {
            builder.addStatement("builder.option($T.FIPS_ENDPOINT_ENABLED, finalServiceConfig.fipsModeEnabled())",
                                 AwsClientOption.class);
        }

        if (model.getEndpointOperation().isPresent()) {
            builder.addStatement("builder.option($T.ENDPOINT_DISCOVERY_ENABLED, endpointDiscoveryEnabled)\n",
                            SdkClientOption.class);
        }


        if (StringUtils.isNotBlank(model.getCustomizationConfig().getCustomRetryStrategy())) {
            builder.addStatement("builder.option($1T.RETRY_STRATEGY, $2T.resolveRetryStrategy(config))",
                            SdkClientOption.class,
                            PoetUtils.classNameFromFqcn(model.getCustomizationConfig().getCustomRetryStrategy()));
        }

        if (StringUtils.isNotBlank(model.getCustomizationConfig().getCustomRetryPolicy())) {
            builder.beginControlFlow("if (builder.option($T.RETRY_STRATEGY) == null)", SdkClientOption.class);
            builder.addStatement("builder.option($1T.RETRY_POLICY, $2T.resolveRetryPolicy(config))",
                                 SdkClientOption.class,
                                 PoetUtils.classNameFromFqcn(model.getCustomizationConfig().getCustomRetryPolicy()));
            builder.endControlFlow();
        }

        if (StringUtils.isNotBlank(clientConfigClassName)) {
            builder.addStatement("builder.option($T.SERVICE_CONFIGURATION, finalServiceConfig)", SdkClientOption.class);
        }

        if (model.getCustomizationConfig().useGlobalEndpoint()) {
            builder.addStatement("builder.option($1T.USE_GLOBAL_ENDPOINT, "
                                 + "globalEndpointResolver.resolve(config.option($1T.AWS_REGION)))", AwsClientOption.class);
        }

        if (hasClientContextParams() || endpointRulesSpecUtils.useS3Express()) {
            builder.addStatement("builder.option($T.CLIENT_CONTEXT_PARAMS, clientContextParams.build())", SdkClientOption.class);
        }

        if (endpointParamsKnowledgeIndex.hasAccountIdEndpointModeBuiltIn()) {
            builder.addStatement("builder.option($T.$L, resolveAccountIdEndpointMode(config))",
                            AwsClientOption.class, model.getNamingStrategy().getEnumValueName("accountIdEndpointMode"));
        }

        String serviceNameForEnvVar = model.getNamingStrategy().getServiceNameForEnvironmentVariables();
        String serviceNameForSystemProperty = model.getNamingStrategy().getServiceNameForSystemProperties();
        String serviceNameForProfileFile = model.getNamingStrategy().getServiceNameForProfileFile();

        builder.addCode("builder.lazyOptionIfAbsent($T.CLIENT_ENDPOINT_PROVIDER, c ->", SdkClientOption.class)
               .addCode("  $T.builder()", AwsClientEndpointProvider.class)
               .addCode("    .serviceEndpointOverrideEnvironmentVariable($S)", "AWS_ENDPOINT_URL_" + serviceNameForEnvVar)
               .addCode("    .serviceEndpointOverrideSystemProperty($S)", "aws.endpointUrl" + serviceNameForSystemProperty)
               .addCode("    .serviceProfileProperty($S)", serviceNameForProfileFile)
               .addCode("    .serviceEndpointPrefix(serviceEndpointPrefix())")
               .addCode("    .defaultProtocol($S)", "https")
               .addCode("    .region(c.get($T.AWS_REGION))", AwsClientOption.class)
               .addCode("    .profileFile(c.get($T.PROFILE_FILE_SUPPLIER))", SdkClientOption.class)
               .addCode("    .profileName(c.get($T.PROFILE_NAME))", SdkClientOption.class)
               .addCode("    .putAdvancedOption($T.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT,", ServiceMetadataAdvancedOption.class)
               .addCode("        c.get($T.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT))", ServiceMetadataAdvancedOption.class)
               .addCode("    .dualstackEnabled(c.get($T.DUALSTACK_ENDPOINT_ENABLED))", AwsClientOption.class)
               .addCode("    .fipsEnabled(c.get($T.FIPS_ENDPOINT_ENABLED))", AwsClientOption.class)
               .addCode("    .build());");

        if (model.getMetadata().isJsonProtocol()) {
            if (model.getCustomizationConfig().getEnableFastUnmarshaller()) {
                builder.addStatement("builder.option($1T.ENABLE_FAST_UNMARSHALLER, true)",
                                     SdkClientJsonProtocolAdvancedOption.class);
            }
        }

        if (hasRequestAlgorithmMember(model) || hasResponseAlgorithms(model)) {
            builder.addStatement("$T clientConfig = config", SdkClientConfiguration.class);

            if (hasRequestAlgorithmMember(model)) {
                builder.addStatement("builder.lazyOption($T.REQUEST_CHECKSUM_CALCULATION, "
                                     + "c -> resolveRequestChecksumCalculation(clientConfig))", SdkClientOption.class);
            }
            if (hasResponseAlgorithms(model)) {
                builder.addStatement("builder.lazyOption($T.RESPONSE_CHECKSUM_VALIDATION, "
                                     + "c -> resolveResponseChecksumValidation(clientConfig))", SdkClientOption.class);
            }
        }

        builder.addStatement("return builder.build()");
        return builder.build();
    }