Skip to content

Commit 54fa0cb

Browse files
authored
fix: introduce S3-specific client configuration to top-level configuration (#378)
* fix: add other S3 SDK client builder options to top-level configuration
1 parent b907743 commit 54fa0cb

File tree

4 files changed

+307
-9
lines changed

4 files changed

+307
-9
lines changed

src/main/java/software/amazon/encryption/s3/S3AsyncEncryptionClient.java

+68-4
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
66
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
77
import software.amazon.awssdk.awscore.AwsRequestOverrideConfiguration;
8-
import software.amazon.awssdk.awscore.client.builder.AwsAsyncClientBuilder;
98
import software.amazon.awssdk.awscore.exception.AwsServiceException;
109
import software.amazon.awssdk.core.async.AsyncRequestBody;
1110
import software.amazon.awssdk.core.async.AsyncResponseTransformer;
@@ -18,6 +17,8 @@
1817
import software.amazon.awssdk.services.kms.KmsClient;
1918
import software.amazon.awssdk.services.s3.DelegatingS3AsyncClient;
2019
import software.amazon.awssdk.services.s3.S3AsyncClient;
20+
import software.amazon.awssdk.services.s3.S3AsyncClientBuilder;
21+
import software.amazon.awssdk.services.s3.S3Configuration;
2122
import software.amazon.awssdk.services.s3.internal.crt.S3CrtAsyncClient;
2223
import software.amazon.awssdk.services.s3.model.DeleteObjectRequest;
2324
import software.amazon.awssdk.services.s3.model.DeleteObjectResponse;
@@ -47,6 +48,7 @@
4748
import java.security.SecureRandom;
4849
import java.util.List;
4950
import java.util.Map;
51+
import java.util.Optional;
5052
import java.util.concurrent.CompletableFuture;
5153
import java.util.function.Consumer;
5254
import java.util.function.Function;
@@ -259,7 +261,7 @@ public void close() {
259261

260262
// This is very similar to the S3EncryptionClient builder
261263
// Make sure to keep both clients in mind when adding new builder options
262-
public static class Builder implements AwsAsyncClientBuilder<Builder, S3AsyncEncryptionClient> {
264+
public static class Builder implements S3AsyncClientBuilder {
263265
private S3AsyncClient _wrappedClient;
264266
private CryptographicMaterialsManager _cryptoMaterialsManager;
265267
private Keyring _keyring;
@@ -286,6 +288,11 @@ public static class Builder implements AwsAsyncClientBuilder<Builder, S3AsyncEnc
286288
private ClientAsyncConfiguration _clientAsyncConfiguration = null;
287289
private SdkAsyncHttpClient _sdkAsyncHttpClient = null;
288290
private SdkAsyncHttpClient.Builder _sdkAsyncHttpClientBuilder = null;
291+
private S3Configuration _serviceConfiguration = null;
292+
private Boolean _accelerate = null;
293+
private Boolean _disableMultiRegionAccessPoints = null;
294+
private Boolean _forcePathStyle = null;
295+
private Boolean _useArnRegion = null;
289296

290297
private Builder() {
291298
}
@@ -548,7 +555,7 @@ public Builder region(Region region) {
548555
* <p>If the setting is not found in any of the locations above, 'false' will be used.
549556
*/
550557
public Builder dualstackEnabled(Boolean isDualStackEnabled) {
551-
_dualStackEnabled = isDualStackEnabled;
558+
_dualStackEnabled = Optional.ofNullable(isDualStackEnabled).orElse(Boolean.FALSE);
552559
return this;
553560
}
554561

@@ -569,7 +576,7 @@ public Builder dualstackEnabled(Boolean isDualStackEnabled) {
569576
* <p>If the setting is not found in any of the locations above, 'false' will be used.
570577
*/
571578
public Builder fipsEnabled(Boolean isFipsEnabled) {
572-
_fipsEnabled = isFipsEnabled;
579+
_fipsEnabled = Optional.ofNullable(isFipsEnabled).orElse(Boolean.FALSE);
573580
return this;
574581
}
575582

@@ -661,6 +668,57 @@ public Builder httpClientBuilder(SdkAsyncHttpClient.Builder httpClientBuilder) {
661668
return this;
662669
}
663670

671+
@Override
672+
public Builder serviceConfiguration(S3Configuration serviceConfiguration) {
673+
_serviceConfiguration = serviceConfiguration;
674+
return this;
675+
}
676+
677+
/**
678+
* Enables this client to use S3 Transfer Acceleration endpoints.
679+
*
680+
* @param accelerate
681+
*/
682+
@Override
683+
public Builder accelerate(Boolean accelerate) {
684+
_accelerate = accelerate;
685+
return this;
686+
}
687+
688+
/**
689+
* Disables this client's usage of Multi-Region Access Points.
690+
*
691+
* @param disableMultiRegionAccessPoints
692+
*/
693+
@Override
694+
public Builder disableMultiRegionAccessPoints(Boolean disableMultiRegionAccessPoints) {
695+
_disableMultiRegionAccessPoints = disableMultiRegionAccessPoints;
696+
return this;
697+
}
698+
699+
/**
700+
* Forces this client to use path-style addressing for buckets.
701+
*
702+
* @param forcePathStyle
703+
*/
704+
@Override
705+
public Builder forcePathStyle(Boolean forcePathStyle) {
706+
_forcePathStyle = forcePathStyle;
707+
return this;
708+
}
709+
710+
/**
711+
* Enables this client to use an ARN's region when constructing an endpoint instead of the client's configured
712+
* region.
713+
*
714+
* @param useArnRegion
715+
*/
716+
@Override
717+
public Builder useArnRegion(Boolean useArnRegion) {
718+
_useArnRegion = useArnRegion;
719+
return this;
720+
}
721+
664722
/**
665723
* Validates and builds the S3AsyncEncryptionClient according
666724
* to the configuration options passed to the Builder object.
@@ -690,6 +748,11 @@ public S3AsyncEncryptionClient build() {
690748
.asyncConfiguration(_clientAsyncConfiguration != null ? _clientAsyncConfiguration : ClientAsyncConfiguration.builder().build())
691749
.httpClient(_sdkAsyncHttpClient)
692750
.httpClientBuilder(_sdkAsyncHttpClientBuilder)
751+
.serviceConfiguration(_serviceConfiguration)
752+
.accelerate(_accelerate)
753+
.disableMultiRegionAccessPoints(_disableMultiRegionAccessPoints)
754+
.forcePathStyle(_forcePathStyle)
755+
.useArnRegion(_useArnRegion)
693756
.build();
694757
}
695758

@@ -733,5 +796,6 @@ public S3AsyncEncryptionClient build() {
733796

734797
return new S3AsyncEncryptionClient(this);
735798
}
799+
736800
}
737801
}

src/main/java/software/amazon/encryption/s3/S3EncryptionClient.java

+162-5
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,27 @@
55
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
66
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
77
import software.amazon.awssdk.awscore.AwsRequestOverrideConfiguration;
8-
import software.amazon.awssdk.awscore.client.builder.AwsClientBuilder;
98
import software.amazon.awssdk.awscore.exception.AwsServiceException;
109
import software.amazon.awssdk.core.ResponseInputStream;
1110
import software.amazon.awssdk.core.async.AsyncRequestBody;
1211
import software.amazon.awssdk.core.async.AsyncResponseTransformer;
12+
import software.amazon.awssdk.core.client.builder.SdkSyncClientBuilder;
1313
import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration;
1414
import software.amazon.awssdk.core.exception.SdkClientException;
1515
import software.amazon.awssdk.core.interceptor.ExecutionAttribute;
1616
import software.amazon.awssdk.core.sync.RequestBody;
1717
import software.amazon.awssdk.core.sync.ResponseTransformer;
1818
import software.amazon.awssdk.endpoints.EndpointProvider;
1919
import software.amazon.awssdk.http.AbortableInputStream;
20+
import software.amazon.awssdk.http.SdkHttpClient;
21+
import software.amazon.awssdk.http.async.SdkAsyncHttpClient;
2022
import software.amazon.awssdk.regions.Region;
2123
import software.amazon.awssdk.services.kms.KmsClient;
2224
import software.amazon.awssdk.services.s3.DelegatingS3Client;
2325
import software.amazon.awssdk.services.s3.S3AsyncClient;
26+
import software.amazon.awssdk.services.s3.S3BaseClientBuilder;
2427
import software.amazon.awssdk.services.s3.S3Client;
28+
import software.amazon.awssdk.services.s3.S3Configuration;
2529
import software.amazon.awssdk.services.s3.model.AbortMultipartUploadRequest;
2630
import software.amazon.awssdk.services.s3.model.AbortMultipartUploadResponse;
2731
import software.amazon.awssdk.services.s3.model.CompleteMultipartUploadRequest;
@@ -65,6 +69,7 @@
6569
import java.util.ArrayList;
6670
import java.util.List;
6771
import java.util.Map;
72+
import java.util.Optional;
6873
import java.util.concurrent.CompletableFuture;
6974
import java.util.concurrent.CompletionException;
7075
import java.util.concurrent.ExecutionException;
@@ -507,9 +512,9 @@ public void close() {
507512
_wrappedAsyncClient.close();
508513
}
509514

510-
// This is very similar to the S3EncryptionClient builder
515+
// This is very similar to the S3AsyncEncryptionClient builder
511516
// Make sure to keep both clients in mind when adding new builder options
512-
public static class Builder implements AwsClientBuilder {
517+
public static class Builder implements S3BaseClientBuilder<Builder, S3EncryptionClient>, SdkSyncClientBuilder<Builder, S3EncryptionClient> {
513518
// The non-encrypted APIs will use a default client.
514519
private S3Client _wrappedClient;
515520
private S3AsyncClient _wrappedAsyncClient;
@@ -536,6 +541,15 @@ public static class Builder implements AwsClientBuilder {
536541
private ClientOverrideConfiguration _overrideConfiguration = null;
537542
// this should only be applied to S3 clients
538543
private URI _endpointOverride = null;
544+
private S3Configuration _serviceConfiguration = null;
545+
private Boolean _accelerate = null;
546+
private Boolean _disableMultiRegionAccessPoints = null;
547+
private Boolean _forcePathStyle = null;
548+
private Boolean _useArnRegion = null;
549+
private SdkHttpClient _httpClient = null;
550+
private SdkHttpClient.Builder _httpClientBuilder = null;
551+
private SdkAsyncHttpClient _asyncHttpClient = null;
552+
private SdkAsyncHttpClient.Builder _asyncHttpClientBuilder = null;
539553

540554
private Builder() {
541555
}
@@ -811,7 +825,7 @@ public Builder region(Region region) {
811825
*/
812826
@Override
813827
public Builder dualstackEnabled(Boolean isDualStackEnabled) {
814-
_dualStackEnabled = isDualStackEnabled;
828+
_dualStackEnabled = Optional.ofNullable(isDualStackEnabled).orElse(Boolean.FALSE);
815829
return this;
816830
}
817831

@@ -833,7 +847,7 @@ public Builder dualstackEnabled(Boolean isDualStackEnabled) {
833847
*/
834848
@Override
835849
public Builder fipsEnabled(Boolean isFipsEnabled) {
836-
_fipsEnabled = isFipsEnabled;
850+
_fipsEnabled = Optional.ofNullable(isFipsEnabled).orElse(Boolean.FALSE);
837851
return this;
838852
}
839853

@@ -876,6 +890,135 @@ public Builder endpointOverride(URI endpointOverride) {
876890
return this;
877891
}
878892

893+
@Override
894+
public Builder serviceConfiguration(S3Configuration serviceConfiguration) {
895+
_serviceConfiguration = serviceConfiguration;
896+
return this;
897+
}
898+
899+
/**
900+
* Enables this client to use S3 Transfer Acceleration endpoints.
901+
*
902+
* @param accelerate
903+
*/
904+
@Override
905+
public Builder accelerate(Boolean accelerate) {
906+
_accelerate = accelerate;
907+
return this;
908+
}
909+
910+
/**
911+
* Disables this client's usage of Multi-Region Access Points.
912+
*
913+
* @param disableMultiRegionAccessPoints
914+
*/
915+
@Override
916+
public Builder disableMultiRegionAccessPoints(Boolean disableMultiRegionAccessPoints) {
917+
_disableMultiRegionAccessPoints = disableMultiRegionAccessPoints;
918+
return this;
919+
}
920+
921+
/**
922+
* Forces this client to use path-style addressing for buckets.
923+
*
924+
* @param forcePathStyle
925+
*/
926+
@Override
927+
public Builder forcePathStyle(Boolean forcePathStyle) {
928+
_forcePathStyle = forcePathStyle;
929+
return this;
930+
}
931+
932+
/**
933+
* Enables this client to use an ARN's region when constructing an endpoint instead of the client's configured
934+
* region.
935+
*
936+
* @param useArnRegion
937+
*/
938+
@Override
939+
public Builder useArnRegion(Boolean useArnRegion) {
940+
_useArnRegion = useArnRegion;
941+
return this;
942+
}
943+
944+
/**
945+
* Sets the {@link SdkHttpClient} that the SDK service client will use to make HTTP calls. This HTTP client may be
946+
* shared between multiple SDK service clients to share a common connection pool. To create a client you must use an
947+
* implementation-specific builder. Note that this method is only recommended when you wish to share an HTTP client across
948+
* multiple SDK service clients. If you do not wish to share HTTP clients, it is recommended to use
949+
* {@link #httpClientBuilder(SdkHttpClient.Builder)} so that service-specific default configuration may be applied.
950+
*
951+
* <p>
952+
* <b>This client must be closed by the user when it is ready to be disposed. The SDK will not close the HTTP client
953+
* when the service client is closed.</b>
954+
* </p>
955+
*
956+
* @param httpClient
957+
*/
958+
@Override
959+
public Builder httpClient(SdkHttpClient httpClient) {
960+
_httpClient = httpClient;
961+
return this;
962+
}
963+
964+
/**
965+
* Sets a {@link SdkHttpClient.Builder} that will be used to obtain a configured instance of {@link SdkHttpClient}. Any
966+
* service-specific HTTP configuration will be merged with the builder's configuration prior to creating the client. When
967+
* there is no desire to share HTTP clients across multiple service clients, the client builder is the preferred way to
968+
* customize the HTTP client as it benefits from service-specific default configuration.
969+
*
970+
* <p>
971+
* <b>Clients created by the builder are managed by the SDK and will be closed when the service client is closed.</b>
972+
* </p>
973+
*
974+
* @param httpClientBuilder
975+
*/
976+
@Override
977+
public Builder httpClientBuilder(SdkHttpClient.Builder httpClientBuilder) {
978+
_httpClientBuilder = httpClientBuilder;
979+
return this;
980+
}
981+
982+
/**
983+
* Sets the {@link SdkAsyncHttpClient} that the SDK service client will use to make HTTP calls. This HTTP client may be
984+
* shared between multiple SDK service clients to share a common connection pool. To create a client you must use an
985+
* implementation specific builder. Note that this method is only recommended when you wish to share an HTTP client across
986+
* multiple SDK service clients. If you do not wish to share HTTP clients, it is recommended to use
987+
* {@link #asyncHttpClientBuilder(SdkAsyncHttpClient.Builder)} so that service specific default configuration may be applied.
988+
* In the S3 Encryption Client, this configuration is applied to the inner async client.
989+
*
990+
* <p>
991+
* <b>This client must be closed by the caller when it is ready to be disposed. The SDK will not close the HTTP client
992+
* when the service client is closed.</b>
993+
* </p>
994+
*
995+
* @param asyncHttpClient
996+
* @return This builder for method chaining.
997+
*/
998+
public Builder asyncHttpClient(SdkAsyncHttpClient asyncHttpClient) {
999+
_asyncHttpClient = asyncHttpClient;
1000+
return this;
1001+
}
1002+
1003+
/**
1004+
* Sets a custom HTTP client builder that will be used to obtain a configured instance of {@link SdkAsyncHttpClient}. Any
1005+
* service specific HTTP configuration will be merged with the builder's configuration prior to creating the client. When
1006+
* there is no desire to share HTTP clients across multiple service clients, the client builder is the preferred way to
1007+
* customize the HTTP client as it benefits from service specific defaults.
1008+
* In the S3 Encryption Client, this configuration is applied to the inner async client.
1009+
*
1010+
* <p>
1011+
* <b>Clients created by the builder are managed by the SDK and will be closed when the service client is closed.</b>
1012+
* </p>
1013+
*
1014+
* @param asyncHttpClientBuilder
1015+
* @return This builder for method chaining.
1016+
*/
1017+
public Builder asyncHttpClientBuilder(SdkAsyncHttpClient.Builder asyncHttpClientBuilder) {
1018+
_asyncHttpClientBuilder = asyncHttpClientBuilder;
1019+
return this;
1020+
}
1021+
8791022
/**
8801023
* Validates and builds the S3EncryptionClient according
8811024
* to the configuration options passed to the Builder object.
@@ -902,6 +1045,13 @@ public S3EncryptionClient build() {
9021045
.fipsEnabled(_fipsEnabled)
9031046
.overrideConfiguration(_overrideConfiguration)
9041047
.endpointOverride(_endpointOverride)
1048+
.serviceConfiguration(_serviceConfiguration)
1049+
.accelerate(_accelerate)
1050+
.disableMultiRegionAccessPoints(_disableMultiRegionAccessPoints)
1051+
.forcePathStyle(_forcePathStyle)
1052+
.useArnRegion(_useArnRegion)
1053+
.httpClient(_httpClient)
1054+
.httpClientBuilder(_httpClientBuilder)
9051055
.build();
9061056
}
9071057

@@ -913,6 +1063,13 @@ public S3EncryptionClient build() {
9131063
.fipsEnabled(_fipsEnabled)
9141064
.overrideConfiguration(_overrideConfiguration)
9151065
.endpointOverride(_endpointOverride)
1066+
.serviceConfiguration(_serviceConfiguration)
1067+
.accelerate(_accelerate)
1068+
.disableMultiRegionAccessPoints(_disableMultiRegionAccessPoints)
1069+
.forcePathStyle(_forcePathStyle)
1070+
.useArnRegion(_useArnRegion)
1071+
.httpClient(_asyncHttpClient)
1072+
.httpClientBuilder(_asyncHttpClientBuilder)
9161073
.build();
9171074
}
9181075

0 commit comments

Comments
 (0)