1 /*
2  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License").
5  * You may not use this file except in compliance with the License.
6  * A copy of the License is located at
7  *
8  *  http://aws.amazon.com/apache2.0
9  *
10  * or in the "license" file accompanying this file. This file is distributed
11  * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12  * express or implied. See the License for the specific language governing
13  * permissions and limitations under the License.
14  */

15
16 package software.amazon.awssdk.services.s3;
17
18 import software.amazon.awssdk.annotations.Immutable;
19 import software.amazon.awssdk.annotations.NotThreadSafe;
20 import software.amazon.awssdk.annotations.SdkPublicApi;
21 import software.amazon.awssdk.annotations.ThreadSafe;
22 import software.amazon.awssdk.core.ServiceConfiguration;
23 import software.amazon.awssdk.profiles.ProfileFile;
24 import software.amazon.awssdk.profiles.ProfileFileSystemSetting;
25 import software.amazon.awssdk.services.s3.internal.FieldWithDefault;
26 import software.amazon.awssdk.services.s3.internal.usearnregion.UseArnRegionProviderChain;
27 import software.amazon.awssdk.services.s3.model.PutBucketAccelerateConfigurationRequest;
28 import software.amazon.awssdk.utils.builder.CopyableBuilder;
29 import software.amazon.awssdk.utils.builder.ToCopyableBuilder;
30
31 @SdkPublicApi
32 @Immutable
33 @ThreadSafe
34 public final class S3Configuration implements ServiceConfiguration, ToCopyableBuilder<S3Configuration.Builder, S3Configuration> {
35     /**
36      * The default setting for use of path style addressing.
37      */

38     private static final boolean DEFAULT_PATH_STYLE_ACCESS_ENABLED = false;
39
40     /**
41      * S3 accelerate is by default not enabled
42      */

43     private static final boolean DEFAULT_ACCELERATE_MODE_ENABLED = false;
44
45     /**
46      * S3 dualstack endpoint is by default not enabled
47      */

48     private static final boolean DEFAULT_DUALSTACK_ENABLED = false;
49
50     /**
51      * S3 payload checksum validation is by default enabled;
52      */

53     private static final boolean DEFAULT_CHECKSUM_VALIDATION_ENABLED = true;
54
55     /**
56      * S3 The default value for enabling chunked encoding for {@link
57      * software.amazon.awssdk.services.s3.model.PutObjectRequest} and {@link
58      * software.amazon.awssdk.services.s3.model.UploadPartRequest}.
59      */

60     private static final boolean DEFAULT_CHUNKED_ENCODING_ENABLED = true;
61
62     private final FieldWithDefault<Boolean> pathStyleAccessEnabled;
63     private final FieldWithDefault<Boolean> accelerateModeEnabled;
64     private final FieldWithDefault<Boolean> dualstackEnabled;
65     private final FieldWithDefault<Boolean> checksumValidationEnabled;
66     private final FieldWithDefault<Boolean> chunkedEncodingEnabled;
67     private final FieldWithDefault<Boolean> useArnRegionEnabled;
68     private final FieldWithDefault<ProfileFile> profileFile;
69     private final FieldWithDefault<String> profileName;
70
71     private S3Configuration(DefaultS3ServiceConfigurationBuilder builder) {
72         this.dualstackEnabled = FieldWithDefault.create(builder.dualstackEnabled, DEFAULT_DUALSTACK_ENABLED);
73         this.accelerateModeEnabled = FieldWithDefault.create(builder.accelerateModeEnabled, DEFAULT_ACCELERATE_MODE_ENABLED);
74         this.pathStyleAccessEnabled = FieldWithDefault.create(builder.pathStyleAccessEnabled, DEFAULT_PATH_STYLE_ACCESS_ENABLED);
75         this.checksumValidationEnabled =  FieldWithDefault.create(builder.checksumValidationEnabled,
76                                                                  DEFAULT_CHECKSUM_VALIDATION_ENABLED);
77         this.chunkedEncodingEnabled = FieldWithDefault.create(builder.chunkedEncodingEnabled, DEFAULT_CHUNKED_ENCODING_ENABLED);
78         this.profileFile = FieldWithDefault.createLazy(builder.profileFile, ProfileFile::defaultProfileFile);
79         this.profileName = FieldWithDefault.create(builder.profileName,
80                                                    ProfileFileSystemSetting.AWS_PROFILE.getStringValueOrThrow());
81         this.useArnRegionEnabled = FieldWithDefault.createLazy(builder.useArnRegionEnabled, this::resolveUserArnRegionEnabled);
82
83         if (accelerateModeEnabled() && pathStyleAccessEnabled()) {
84             throw new IllegalArgumentException("Accelerate mode cannot be used with path style addressing");
85         }
86     }
87
88     private boolean resolveUserArnRegionEnabled() {
89         return UseArnRegionProviderChain.create(this.profileFile.value(), this.profileName.value())
90                                         .resolveUseArnRegion()
91                                         .orElse(false);
92     }
93
94     /**
95      * Create a {@link Builder}, used to create a {@link S3Configuration}.
96      */

97     public static Builder builder() {
98         return new DefaultS3ServiceConfigurationBuilder();
99     }
100
101     /**
102      * <p>
103      * Returns whether the client uses path-style access for all requests.
104      * </p>
105      * <p>
106      * Amazon S3 supports virtual-hosted-style and path-style access in all
107      * Regions. The path-style syntax, however, requires that you use the
108      * region-specific endpoint when attempting to access a bucket.
109      * </p>
110      * <p>
111      * The default behaviour is to detect which access style to use based on
112      * the configured endpoint (an IP will result in path-style access) and
113      * the bucket being accessed (some buckets are not valid DNS names).
114      * Setting this flag will result in path-style access being used for all
115      * requests.
116      * </p>
117      *
118      * @return True is the client should always use path-style access
119      */

120     public boolean pathStyleAccessEnabled() {
121         return pathStyleAccessEnabled.value();
122     }
123
124     /**
125      * <p>
126      * Returns whether the client has enabled accelerate mode for getting and putting objects.
127      * </p>
128      * <p>
129      * The default behavior is to disable accelerate mode for any operations (GET, PUT, DELETE). You need to call
130      * {@link DefaultS3Client#putBucketAccelerateConfiguration(PutBucketAccelerateConfigurationRequest)}
131      * first to use this feature.
132      * </p>
133      *
134      * @return True if accelerate mode is enabled.
135      */

136     public boolean accelerateModeEnabled() {
137         return accelerateModeEnabled.value();
138     }
139
140     /**
141      * <p>
142      * Returns whether the client is configured to use dualstack mode for
143      * accessing S3. If you want to use IPv6 when accessing S3, dualstack
144      * must be enabled.
145      * </p>
146      *
147      * <p>
148      * Dualstack endpoints are disabled by default.
149      * </p>
150      *
151      * @return True if the client will use the dualstack endpoints
152      */

153     public boolean dualstackEnabled() {
154         return dualstackEnabled.value();
155     }
156
157     public boolean checksumValidationEnabled() {
158         return checksumValidationEnabled.value();
159     }
160
161     /**
162      * Returns whether the client should use chunked encoding when signing the
163      * payload body.
164      * <p>
165      * This option only currently applies to {@link
166      * software.amazon.awssdk.services.s3.model.PutObjectRequest} and {@link
167      * software.amazon.awssdk.services.s3.model.UploadPartRequest}.
168      *
169      * @return True if chunked encoding should be used.
170      */

171     public boolean chunkedEncodingEnabled() {
172         return chunkedEncodingEnabled.value();
173     }
174
175     /**
176      * Returns whether the client is allowed to make cross-region calls when an S3 Access Point ARN has a different
177      * region to the one configured on the client.
178      * <p>
179      * @return True if a different region in the ARN can be used.
180      */

181     public boolean useArnRegionEnabled() {
182         return useArnRegionEnabled.value();
183     }
184
185     @Override
186     public Builder toBuilder() {
187         return builder()
188                 .dualstackEnabled(dualstackEnabled.valueOrNullIfDefault())
189                 .accelerateModeEnabled(accelerateModeEnabled.valueOrNullIfDefault())
190                 .pathStyleAccessEnabled(pathStyleAccessEnabled.valueOrNullIfDefault())
191                 .checksumValidationEnabled(checksumValidationEnabled.valueOrNullIfDefault())
192                 .chunkedEncodingEnabled(chunkedEncodingEnabled.valueOrNullIfDefault())
193                 .useArnRegionEnabled(useArnRegionEnabled.valueOrNullIfDefault())
194                 .profileFile(profileFile.valueOrNullIfDefault())
195                 .profileName(profileName.valueOrNullIfDefault());
196     }
197
198     @NotThreadSafe
199     public interface Builder extends CopyableBuilder<Builder, S3Configuration> {
200         Boolean dualstackEnabled();
201
202         /**
203          * Option to enable using the dualstack endpoints when accessing S3. Dualstack
204          * should be enabled if you want to use IPv6.
205          *
206          * <p>
207          * Dualstack endpoints are disabled by default.
208          * </p>
209          *
210          * @see S3Configuration#dualstackEnabled().
211          */

212         Builder dualstackEnabled(Boolean dualstackEnabled);
213
214         Boolean accelerateModeEnabled();
215
216         /**
217          * Option to enable using the accelerate enedpoint when accessing S3. Accelerate
218          * endpoints allow faster transfer of objects by using Amazon CloudFront's
219          * globally distributed edge locations.
220          *
221          * <p>
222          * Accelerate mode is disabled by default.
223          * </p>
224          *
225          * @see S3Configuration#accelerateModeEnabled().
226          */

227         Builder accelerateModeEnabled(Boolean accelerateModeEnabled);
228
229         Boolean pathStyleAccessEnabled();
230
231         /**
232          * Option to enable using path style access for accessing S3 objects
233          * instead of DNS style access. DNS style access is preferred as it
234          * will result in better load balancing when accessing S3.
235          *
236          * <p>
237          * Path style access is disabled by default. Path style may still be used for legacy
238          * buckets that are not DNS compatible.
239          * </p>
240          *
241          * @see S3Configuration#pathStyleAccessEnabled().
242          */

243         Builder pathStyleAccessEnabled(Boolean pathStyleAccessEnabled);
244
245         Boolean checksumValidationEnabled();
246
247         /**
248          * Option to disable doing a validation of the checksum of an object stored in S3.
249          *
250          * <p>
251          * Checksum validation is enabled by default.
252          * </p>
253          *
254          * @see S3Configuration#checksumValidationEnabled().
255          */

256         Builder checksumValidationEnabled(Boolean checksumValidationEnabled);
257
258         Boolean chunkedEncodingEnabled();
259
260         /**
261          * Option to enable using chunked encoding when signing the request
262          * payload for {@link
263          * software.amazon.awssdk.services.s3.model.PutObjectRequest} and {@link
264          * software.amazon.awssdk.services.s3.model.UploadPartRequest}.
265          *
266          * @see S3Configuration#chunkedEncodingEnabled()
267          */

268         Builder chunkedEncodingEnabled(Boolean chunkedEncodingEnabled);
269
270         Boolean useArnRegionEnabled();
271
272         /**
273          * If an S3 resource ARN is passed in as the target of an S3 operation that has a different region to the one
274          * the client was configured with, this flag must be set to 'true' to permit the client to make a
275          * cross-region call to the region specified in the ARN otherwise an exception will be thrown.
276          *
277          * @see S3Configuration#useArnRegionEnabled()
278          */

279         Builder useArnRegionEnabled(Boolean useArnRegionEnabled);
280
281         ProfileFile profileFile();
282
283         /**
284          * The profile file that should be consulted to determine the default value of {@link #useArnRegionEnabled(Boolean)}.
285          * This is not used, if the {@link #useArnRegionEnabled(Boolean)} is configured.
286          *
287          * <p>
288          * By default, the {@link ProfileFile#defaultProfileFile()} is used.
289          * </p>
290          */

291         Builder profileFile(ProfileFile profileFile);
292
293         String profileName();
294
295         /**
296          * The profile name that should be consulted to determine the default value of {@link #useArnRegionEnabled(Boolean)}.
297          * This is not used, if the {@link #useArnRegionEnabled(Boolean)} is configured.
298          *
299          * <p>
300          * By default, the {@link ProfileFileSystemSetting#AWS_PROFILE} is used.
301          * </p>
302          */

303         Builder profileName(String profileName);
304     }
305
306     static final class DefaultS3ServiceConfigurationBuilder implements Builder {
307         private Boolean dualstackEnabled;
308         private Boolean accelerateModeEnabled;
309         private Boolean pathStyleAccessEnabled;
310         private Boolean checksumValidationEnabled;
311         private Boolean chunkedEncodingEnabled;
312         private Boolean useArnRegionEnabled;
313         private ProfileFile profileFile;
314         private String profileName;
315
316         @Override
317         public Boolean dualstackEnabled() {
318             return dualstackEnabled;
319         }
320
321         public Builder dualstackEnabled(Boolean dualstackEnabled) {
322             this.dualstackEnabled = dualstackEnabled;
323             return this;
324         }
325
326         @Override
327         public Boolean accelerateModeEnabled() {
328             return accelerateModeEnabled;
329         }
330
331         public void setDualstackEnabled(Boolean dualstackEnabled) {
332             dualstackEnabled(dualstackEnabled);
333         }
334
335         public Builder accelerateModeEnabled(Boolean accelerateModeEnabled) {
336             this.accelerateModeEnabled = accelerateModeEnabled;
337             return this;
338         }
339
340         @Override
341         public Boolean pathStyleAccessEnabled() {
342             return pathStyleAccessEnabled;
343         }
344
345         public void setAccelerateModeEnabled(Boolean accelerateModeEnabled) {
346             accelerateModeEnabled(accelerateModeEnabled);
347         }
348
349         public Builder pathStyleAccessEnabled(Boolean pathStyleAccessEnabled) {
350             this.pathStyleAccessEnabled = pathStyleAccessEnabled;
351             return this;
352         }
353
354         @Override
355         public Boolean checksumValidationEnabled() {
356             return checksumValidationEnabled;
357         }
358
359         public void setPathStyleAccessEnabled(Boolean pathStyleAccessEnabled) {
360             pathStyleAccessEnabled(pathStyleAccessEnabled);
361         }
362
363         public Builder checksumValidationEnabled(Boolean checksumValidationEnabled) {
364             this.checksumValidationEnabled = checksumValidationEnabled;
365             return this;
366         }
367
368         @Override
369         public Boolean chunkedEncodingEnabled() {
370             return chunkedEncodingEnabled;
371         }
372
373         public void setChecksumValidationEnabled(Boolean checksumValidationEnabled) {
374             checksumValidationEnabled(checksumValidationEnabled);
375         }
376
377         public Builder chunkedEncodingEnabled(Boolean chunkedEncodingEnabled) {
378             this.chunkedEncodingEnabled = chunkedEncodingEnabled;
379             return this;
380         }
381
382         @Override
383         public Boolean useArnRegionEnabled() {
384             return useArnRegionEnabled;
385         }
386
387         public void setChunkedEncodingEnabled(Boolean chunkedEncodingEnabled) {
388             chunkedEncodingEnabled(chunkedEncodingEnabled);
389         }
390
391         public Builder useArnRegionEnabled(Boolean useArnRegionEnabled) {
392             this.useArnRegionEnabled = useArnRegionEnabled;
393             return this;
394         }
395
396         @Override
397         public ProfileFile profileFile() {
398             return profileFile;
399         }
400
401         @Override
402         public Builder profileFile(ProfileFile profileFile) {
403             this.profileFile = profileFile;
404             return this;
405         }
406
407         @Override
408         public String profileName() {
409             return profileName;
410         }
411
412         @Override
413         public Builder profileName(String profileName) {
414             this.profileName = profileName;
415             return this;
416         }
417
418         public void setUseArnRegionEnabled(Boolean useArnRegionEnabled) {
419             useArnRegionEnabled(useArnRegionEnabled);
420         }
421
422         public S3Configuration build() {
423             return new S3Configuration(this);
424         }
425     }
426 }
427