Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changes/next-release/feature-AWSSDKforJavav2-70eb163.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"type": "feature",
"category": "AWS SDK for Java v2",
"contributor": "",
"description": "Cross region bucket access for S3 Client. This feature will allow users to access buckets of different region using a single cross region configured client."
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,6 @@ class CommonGeneratorTasks extends CompositeGeneratorTask {
new ModelClassGeneratorTasks(params),
new PackageInfoGeneratorTasks(params),
new BaseExceptionClassGeneratorTasks(params),
new ClientOptionsClassGeneratorTasks(params));
new CommonInternalGeneratorTasks(params));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,35 @@

package software.amazon.awssdk.codegen.emitters.tasks;

import java.util.Collections;
import java.util.Arrays;
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.client.SdkClientOptions;
import software.amazon.awssdk.codegen.poet.common.UserAgentUtilsSpec;

public class ClientOptionsClassGeneratorTasks extends BaseGeneratorTasks {
public class CommonInternalGeneratorTasks extends BaseGeneratorTasks {
private final GeneratorTaskParams params;

public ClientOptionsClassGeneratorTasks(GeneratorTaskParams params) {
public CommonInternalGeneratorTasks(GeneratorTaskParams params) {
super(params);
this.params = params;
}

@Override
protected List<GeneratorTask> createTasks() throws Exception {
return Collections.singletonList(
new PoetGeneratorTask(clientOptionsDir(), params.getModel().getFileHeader(), new SdkClientOptions(params.getModel()))
);
return Arrays.asList(createClientOptionTask(), createUserAgentTask());
}

private PoetGeneratorTask createClientOptionTask() {
return new PoetGeneratorTask(clientOptionsDir(), params.getModel().getFileHeader(),
new SdkClientOptions(params.getModel()));
}

private PoetGeneratorTask createUserAgentTask() {
return new PoetGeneratorTask(clientOptionsDir(), params.getModel().getFileHeader(),
new UserAgentUtilsSpec(params.getModel()));
}

private String clientOptionsDir() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import software.amazon.awssdk.awscore.internal.client.ClientComposer;
import software.amazon.awssdk.core.retry.RetryMode;
import software.amazon.awssdk.core.traits.PayloadTrait;
import software.amazon.awssdk.utils.AttributeMap;
Expand Down Expand Up @@ -212,6 +213,20 @@ public class CustomizationConfig {
*/
private boolean delegateSyncClientClass;

/**
* Fully qualified name of a class that given the default sync client instance can return the final client instance,
* for instance by decorating the client with specific-purpose implementations of the client interface.
* The class should implement the {@link ClientComposer} interface. See S3 customization.config for an example.
*/
private String syncClientComposer;

/**
* Fully qualified name of a class that given the default async client instance can return the final client instance,
* for instance by decorating the client with specific-purpose implementations of the client interface.
* The class should implement the {@link ClientComposer} interface. See S3 customization.config for an example.
*/
private String asyncClientComposer;

/**
* Whether to skip generating endpoint tests from endpoint-tests.json
*/
Expand Down Expand Up @@ -566,6 +581,22 @@ public void setDelegateAsyncClientClass(boolean delegateAsyncClientClass) {
this.delegateAsyncClientClass = delegateAsyncClientClass;
}

public String getSyncClientComposer() {
return syncClientComposer;
}

public void setSyncClientComposer(String syncClientComposer) {
this.syncClientComposer = syncClientComposer;
}

public String getAsyncClientComposer() {
return asyncClientComposer;
}

public void setAsyncClientComposer(String asyncClientComposer) {
this.asyncClientComposer = asyncClientComposer;
}

public boolean isDelegateSyncClientClass() {
return delegateSyncClientClass;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ public class ServiceConfig {

private boolean hasAccelerateModeEnabledProperty = false;

private boolean hasCrossRegionAccessEnabledProperty = false;

public String getClassName() {
return className;
}
Expand Down Expand Up @@ -95,6 +97,14 @@ public void setHasPathStyleAccessEnabledProperty(boolean hasPathStyleAccessEnabl
this.hasPathStyleAccessEnabledProperty = hasPathStyleAccessEnabledProperty;
}

public boolean hasCrossRegionAccessEnabledProperty() {
return hasCrossRegionAccessEnabledProperty;
}

public void setHasCrossRegionAccessEnabledProperty(boolean hasCrossRegionAccessEnabledProperty) {
this.hasCrossRegionAccessEnabledProperty = hasCrossRegionAccessEnabledProperty;
}

public boolean hasAccelerateModeEnabledProperty() {
return hasAccelerateModeEnabledProperty;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,21 @@ public String getSdkResponseBaseClassName() {
}
}

public Optional<String> syncClientComposerClassName() {
if (customizationConfig.getSyncClientComposer() != null) {
return Optional.of(customizationConfig.getSyncClientComposer());
}
return Optional.empty();
}

public Optional<String> asyncClientComposerClassName() {
String asyncClientComposer = customizationConfig.getAsyncClientComposer();
if (customizationConfig.getAsyncClientComposer() != null) {
return Optional.of(asyncClientComposer);
}
return Optional.empty();
}

public String getFileHeader() {
return FILE_HEADER;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ public ClassName getServiceConfigClass() {
+ model.getMetadata().getServiceName() + "ServiceClientConfiguration");
}

public ClassName getUserAgentClass() {
return ClassName.get(model.getMetadata().getFullClientInternalPackageName(), "UserAgentUtils");
}

/**
* @param operationName Name of the operation
* @return A Poet {@link ClassName} for the response type of a paginated operation in the base service package.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
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.awscore.internal.client.ClientComposer;
import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
import software.amazon.awssdk.codegen.poet.ClassSpec;
import software.amazon.awssdk.codegen.poet.PoetExtension;
Expand All @@ -37,9 +38,11 @@
import software.amazon.awssdk.core.client.config.SdkClientConfiguration;
import software.amazon.awssdk.core.client.config.SdkClientOption;
import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
import software.amazon.awssdk.endpoints.EndpointProvider;
import software.amazon.awssdk.protocols.query.interceptor.QueryParametersToBodyInterceptor;
import software.amazon.awssdk.utils.CollectionUtils;


public class AsyncClientBuilderClass implements ClassSpec {
private final IntermediateModel model;
private final ClassName clientInterfaceName;
Expand Down Expand Up @@ -86,7 +89,10 @@ public TypeSpec poetSpec() {
builder.addMethod(bearerTokenProviderMethod());
}

return builder.addMethod(buildClientMethod()).build();
builder.addMethod(buildClientMethod());
builder.addMethod(initializeServiceClientConfigMethod());

return builder.build();
}

private MethodSpec endpointDiscoveryEnabled() {
Expand Down Expand Up @@ -126,30 +132,31 @@ private MethodSpec endpointProviderMethod() {
}

private MethodSpec buildClientMethod() {
MethodSpec.Builder b = MethodSpec.methodBuilder("buildClient")
MethodSpec.Builder builder = MethodSpec.methodBuilder("buildClient")
.addAnnotation(Override.class)
.addModifiers(Modifier.PROTECTED, Modifier.FINAL)
.returns(clientInterfaceName)
.addStatement("$T clientConfiguration = super.asyncClientConfiguration()",
SdkClientConfiguration.class);

addQueryProtocolInterceptors(b);

return b.addStatement("this.validateClientOptions(clientConfiguration)")
.addStatement("$T endpointOverride = null", URI.class)
.addCode("if (clientConfiguration.option($T.ENDPOINT_OVERRIDDEN) != null"
+ "&& $T.TRUE.equals(clientConfiguration.option($T.ENDPOINT_OVERRIDDEN))) {"
+ "endpointOverride = clientConfiguration.option($T.ENDPOINT);"
+ "}",
SdkClientOption.class, Boolean.class, SdkClientOption.class, SdkClientOption.class)
.addStatement("$T serviceClientConfiguration = $T.builder()"
+ ".overrideConfiguration(overrideConfiguration())"
+ ".region(clientConfiguration.option($T.AWS_REGION))"
+ ".endpointOverride(endpointOverride)"
+ ".build()",
serviceConfigClassName, serviceConfigClassName, AwsClientOption.class)
.addStatement("return new $T(serviceClientConfiguration, clientConfiguration)", clientClassName)
.build();
SdkClientConfiguration.class).addStatement("this.validateClientOptions"
+ "(clientConfiguration)")
.addStatement("$T serviceClientConfiguration = initializeServiceClientConfig"
+ "(clientConfiguration)",
serviceConfigClassName);

addQueryProtocolInterceptors(builder);


builder.addStatement("$1T client = new $2T(serviceClientConfiguration, clientConfiguration)",
clientInterfaceName, clientClassName);
if (model.asyncClientComposerClassName().isPresent()) {
builder.addStatement("$1T composer = new $2T()",
ClientComposer.class,
PoetUtils.classNameFromFqcn(model.asyncClientComposerClassName().get()));
builder.addStatement("return ($T) composer.compose(client, clientConfiguration)", clientInterfaceName);
} else {
builder.addStatement("return client");
}
return builder.build();
}

private MethodSpec.Builder addQueryProtocolInterceptors(MethodSpec.Builder b) {
Expand Down Expand Up @@ -186,6 +193,29 @@ private MethodSpec bearerTokenProviderMethod() {
.build();
}

private MethodSpec initializeServiceClientConfigMethod() {
return MethodSpec.methodBuilder("initializeServiceClientConfig").addModifiers(Modifier.PRIVATE)
.addParameter(SdkClientConfiguration.class, "clientConfig")
.returns(serviceConfigClassName)
.addStatement("$T endpointOverride = null", URI.class)
.addStatement("$T endpointProvider = clientConfig.option($T.ENDPOINT_PROVIDER)",
EndpointProvider.class,
SdkClientOption.class)
.addCode("if (clientConfig.option($T.ENDPOINT_OVERRIDDEN) != null"
+ "&& $T.TRUE.equals(clientConfig.option($T.ENDPOINT_OVERRIDDEN))) {"
+ "endpointOverride = clientConfig.option($T.ENDPOINT);"
+ "}",
SdkClientOption.class, Boolean.class, SdkClientOption.class, SdkClientOption.class)
.addStatement("return $T.builder()"
+ ".overrideConfiguration(overrideConfiguration())"
+ ".region(clientConfig.option($T.AWS_REGION))"
+ ".endpointOverride(endpointOverride)"
+ ".endpointProvider(endpointProvider)"
+ ".build()",
serviceConfigClassName, AwsClientOption.class)
.build();
}

@Override
public ClassName className() {
return builderClassName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
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.awscore.internal.client.ClientComposer;
import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
import software.amazon.awssdk.codegen.poet.ClassSpec;
import software.amazon.awssdk.codegen.poet.PoetExtension;
Expand All @@ -37,6 +38,7 @@
import software.amazon.awssdk.core.client.config.SdkClientConfiguration;
import software.amazon.awssdk.core.client.config.SdkClientOption;
import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
import software.amazon.awssdk.endpoints.EndpointProvider;
import software.amazon.awssdk.protocols.query.interceptor.QueryParametersToBodyInterceptor;
import software.amazon.awssdk.utils.CollectionUtils;

Expand Down Expand Up @@ -86,7 +88,10 @@ public TypeSpec poetSpec() {
builder.addMethod(tokenProviderMethodImpl());
}

return builder.addMethod(buildClientMethod()).build();
builder.addMethod(buildClientMethod());
builder.addMethod(initializeServiceClientConfigMethod());

return builder.build();
}

private MethodSpec endpointDiscoveryEnabled() {
Expand Down Expand Up @@ -126,30 +131,30 @@ private MethodSpec endpointProviderMethod() {


private MethodSpec buildClientMethod() {
MethodSpec.Builder b = MethodSpec.methodBuilder("buildClient")
MethodSpec.Builder builder = MethodSpec.methodBuilder("buildClient")
.addAnnotation(Override.class)
.addModifiers(Modifier.PROTECTED, Modifier.FINAL)
.returns(clientInterfaceName)
.addStatement("$T clientConfiguration = super.syncClientConfiguration()",
SdkClientConfiguration.class);

addQueryProtocolInterceptors(b);

return b.addStatement("this.validateClientOptions(clientConfiguration)")
.addStatement("$T endpointOverride = null", URI.class)
.addCode("if (clientConfiguration.option($T.ENDPOINT_OVERRIDDEN) != null"
+ "&& $T.TRUE.equals(clientConfiguration.option($T.ENDPOINT_OVERRIDDEN))) {"
+ "endpointOverride = clientConfiguration.option($T.ENDPOINT);"
+ "}",
SdkClientOption.class, Boolean.class, SdkClientOption.class, SdkClientOption.class)
.addStatement("$T serviceClientConfiguration = $T.builder()"
+ ".overrideConfiguration(overrideConfiguration())"
+ ".region(clientConfiguration.option($T.AWS_REGION))"
+ ".endpointOverride(endpointOverride)"
+ ".build()",
serviceConfigClassName, serviceConfigClassName, AwsClientOption.class)
.addStatement("return new $T(serviceClientConfiguration, clientConfiguration)", clientClassName)
.build();
SdkClientConfiguration.class)
.addStatement("this.validateClientOptions(clientConfiguration)")
.addStatement("$T serviceClientConfiguration = initializeServiceClientConfig"
+ "(clientConfiguration)",
serviceConfigClassName);

addQueryProtocolInterceptors(builder);

builder.addStatement("$1T client = new $2T(serviceClientConfiguration, clientConfiguration)",
clientInterfaceName, clientClassName);
if (model.syncClientComposerClassName().isPresent()) {
builder.addStatement("$1T composer = new $2T()",
ClientComposer.class,
PoetUtils.classNameFromFqcn(model.syncClientComposerClassName().get()));
builder.addStatement("return ($T) composer.compose(client, clientConfiguration)", clientInterfaceName);
} else {
builder.addStatement("return client");
}
return builder.build();
}

private MethodSpec.Builder addQueryProtocolInterceptors(MethodSpec.Builder b) {
Expand Down Expand Up @@ -186,6 +191,29 @@ private MethodSpec tokenProviderMethodImpl() {
.build();
}

private MethodSpec initializeServiceClientConfigMethod() {
return MethodSpec.methodBuilder("initializeServiceClientConfig").addModifiers(Modifier.PRIVATE)
.addParameter(SdkClientConfiguration.class, "clientConfig")
.returns(serviceConfigClassName)
.addStatement("$T endpointOverride = null", URI.class)
.addStatement("$T endpointProvider = clientConfig.option($T.ENDPOINT_PROVIDER)",
EndpointProvider.class,
SdkClientOption.class)
.addCode("if (clientConfig.option($T.ENDPOINT_OVERRIDDEN) != null"
+ "&& $T.TRUE.equals(clientConfig.option($T.ENDPOINT_OVERRIDDEN))) {"
+ "endpointOverride = clientConfig.option($T.ENDPOINT);"
+ "}",
SdkClientOption.class, Boolean.class, SdkClientOption.class, SdkClientOption.class)
.addStatement("return $T.builder()"
+ ".overrideConfiguration(overrideConfiguration())"
+ ".region(clientConfig.option($T.AWS_REGION))"
+ ".endpointOverride(endpointOverride)"
+ ".endpointProvider(endpointProvider)"
+ ".build()",
serviceConfigClassName, AwsClientOption.class)
.build();
}

@Override
public ClassName className() {
return builderClassName;
Expand Down
Loading