1 /*
2  * Copyright 2011-2020 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 package com.amazonaws.services.s3;
16
17 import com.amazonaws.ClientConfigurationFactory;
18 import com.amazonaws.annotation.NotThreadSafe;
19 import com.amazonaws.annotation.SdkTestInternalApi;
20 import com.amazonaws.client.builder.AwsSyncClientBuilder;
21 import com.amazonaws.internal.SdkFunction;
22 import com.amazonaws.regions.AwsRegionProvider;
23 import com.amazonaws.services.s3.model.CreateBucketRequest;
24 import com.amazonaws.services.s3.model.PutObjectRequest;
25
26
27 @NotThreadSafe
28 public abstract class AmazonS3Builder<Subclass extends AmazonS3Builder, TypeToBuild extends AmazonS3> extends AwsSyncClientBuilder<Subclass, TypeToBuild> {
29
30     private static final AmazonS3ClientConfigurationFactory CLIENT_CONFIG_FACTORY = new AmazonS3ClientConfigurationFactory();
31
32     private static final SdkFunction<AmazonS3ClientParamsWrapper, AmazonS3> DEFAULT_CLIENT_FACTORY = new SdkFunction<AmazonS3ClientParamsWrapper, AmazonS3>() {
33         @Override
34         public AmazonS3 apply(AmazonS3ClientParamsWrapper params) {
35             return new AmazonS3Client(params);
36         }
37     };
38
39     protected final SdkFunction<AmazonS3ClientParamsWrapper, AmazonS3> clientFactory;
40
41     private Boolean pathStyleAccessEnabled;
42     private Boolean chunkedEncodingDisabled;
43     private Boolean accelerateModeEnabled;
44     private Boolean payloadSigningEnabled;
45     private Boolean dualstackEnabled;
46     private Boolean forceGlobalBucketAccessEnabled;
47     private Boolean useArnRegionEnabled;
48     private Boolean regionalUsEast1EndpointEnabled;
49
50     protected AmazonS3Builder() {
51         super(CLIENT_CONFIG_FACTORY);
52         this.clientFactory = DEFAULT_CLIENT_FACTORY;
53     }
54
55     @SdkTestInternalApi
56     AmazonS3Builder(SdkFunction<AmazonS3ClientParamsWrapper, AmazonS3> clientFactory,
57                     ClientConfigurationFactory clientConfigFactory,
58                     AwsRegionProvider regionProvider) {
59         super(clientConfigFactory, regionProvider);
60         this.clientFactory = clientFactory;
61     }
62
63     /**
64      * @return The current setting for path style access configured in the builder.
65      */

66     public Boolean isPathStyleAccessEnabled() {
67         return pathStyleAccessEnabled;
68     }
69
70     /**
71      * <p>Configures the client to use path-style access for all requests.</p>
72      *
73      * <p>Amazon S3 supports virtual-hosted-style and path-style access in all Regions. The
74      * path-style syntax, however, requires that you use the region-specific endpoint when
75      * attempting to access a bucket.</p>
76      *
77      * <p>The default behaviour is to detect which access style to use based on the configured
78      * endpoint (an IP will result in path-style access) and the bucket being accessed (some buckets
79      * are not valid DNS names). Setting this flag will result in path-style access being used for
80      * all requests.</p>
81      *
82      * @param pathStyleAccessEnabled True to always use path-style access.
83      */

84     public void setPathStyleAccessEnabled(Boolean pathStyleAccessEnabled) {
85         this.pathStyleAccessEnabled = pathStyleAccessEnabled;
86     }
87
88     /**
89      * <p>Configures the client to use path-style access for all requests.</p>
90      *
91      * <p>Amazon S3 supports virtual-hosted-style and path-style access in all Regions. The
92      * path-style syntax, however, requires that you use the region-specific endpoint when
93      * attempting to access a bucket.</p>
94      *
95      * <p> The default behaviour is to detect which access style to use based on the configured
96      * endpoint (an IP will result in path-style access) and the bucket being accessed (some buckets
97      * are not valid DNS names). Setting this flag will result in path-style access being used for
98      * all requests.</p>
99      *
100      * @param pathStyleAccessEnabled True to always use path-style access.
101      * @return This object for method chaining.
102      */

103     public Subclass withPathStyleAccessEnabled(Boolean pathStyleAccessEnabled) {
104         setPathStyleAccessEnabled(pathStyleAccessEnabled);
105         return getSubclass();
106     }
107
108     /**
109      * <p>Enables path style access for clients built via this builder.</p>
110      *
111      * <p>Amazon S3 supports virtual-hosted-style and path-style access in all Regions. The
112      * path-style syntax, however, requires that you use the region-specific endpoint when
113      * attempting to access a bucket.</p>
114      *
115      * <p>The default behaviour is to detect which access style to use based on the configured
116      * endpoint (an IP will result in path-style access) and the bucket being accessed (some buckets
117      * are not valid DNS names). Setting this flag will result in path-style access being used for
118      * all requests.</p>
119      *
120      * @return This object for method chaining.
121      */

122     public Subclass enablePathStyleAccess() {
123         setPathStyleAccessEnabled(Boolean.TRUE);
124         return getSubclass();
125     }
126
127     /**
128      * @return The current setting for chunked encoding configured in the builder.
129      */

130     public Boolean isChunkedEncodingDisabled() {
131         return chunkedEncodingDisabled;
132     }
133
134     /**
135      * <p>Configures the client to disable chunked encoding for all requests.</p>
136      *
137      * <p>The default behavior is to enable chunked encoding automatically for PutObjectRequest and
138      * UploadPartRequest. Setting this flag will result in disabling chunked encoding for all
139      * requests.</p>
140      *
141      * <p><b>Note:</b> Enabling this option has performance implications since the checksum for the
142      * payload will have to be pre-calculated before sending the data. If your payload is large this
143      * will affect the overall time required to upload an object. Using this option is recommended
144      * only if your endpoint does not implement chunked uploading.</p>
145      *
146      * @param chunkedEncodingDisabled True to disable chunked encoding.
147      */

148     public void setChunkedEncodingDisabled(Boolean chunkedEncodingDisabled) {
149         this.chunkedEncodingDisabled = chunkedEncodingDisabled;
150     }
151
152     /**
153      * <p>Configures the client to disable chunked encoding for all requests.</p>
154      *
155      * <p>The default behavior is to enable chunked encoding automatically for PutObjectRequest and
156      * UploadPartRequest. Setting this flag will result in disabling chunked encoding for all
157      * requests.</p>
158      *
159      * <p><b>Note:</b> Enabling this option has performance implications since the checksum for the
160      * payload will have to be pre-calculated before sending the data. If your payload is large this
161      * will affect the overall time required to upload an object. Using this option is recommended
162      * only if your endpoint does not implement chunked uploading.</p>
163      *
164      * @param chunkedEncodingDisabled True to disable chunked encoding.
165      * @return this Builder instance that can be used for method chaining
166      */

167     public Subclass withChunkedEncodingDisabled(Boolean chunkedEncodingDisabled) {
168         setChunkedEncodingDisabled(chunkedEncodingDisabled);
169         return getSubclass();
170     }
171
172     /**
173      * <p>Disables chunked encoding on clients built via the builder.</p>
174      *
175      * <p>The default behavior is to enable chunked encoding automatically for PutObjectRequest and
176      * UploadPartRequest. Setting this flag will result in disabling chunked encoding for all
177      * requests.</p>
178      *
179      * <p><b>Note:</b> Enabling this option has performance implications since the checksum for the
180      * payload will have to be pre-calculated before sending the data. If your payload is large this
181      * will affect the overall time required to upload an object. Using this option is recommended
182      * only if your endpoint does not implement chunked uploading.</p>
183      *
184      * @return this Builder instance that can be used for method chaining
185      */

186     public Subclass disableChunkedEncoding() {
187         setChunkedEncodingDisabled(Boolean.TRUE);
188         return getSubclass();
189     }
190
191     /**
192      * @return The current setting for accelerate mode configured in the builder.
193      */

194     public Boolean isAccelerateModeEnabled() {
195         return accelerateModeEnabled;
196     }
197
198     /**
199      * <p>Configures the client to use S3 accelerate endpoint for all requests.</p>
200      *
201      * <p>A bucket by default cannot be accessed in accelerate mode. If you wish to do so, you need
202      * to enable the accelerate configuration for the bucket in advance. To enable accelerate mode
203      * see {@link com.amazonaws.services.s3.AmazonS3Client#setBucketAccelerateConfiguration(com.amazonaws.services.s3.model.SetBucketAccelerateConfigurationRequest)}.
204      * </p>
205      *
206      * @param accelerateModeEnabled True to enable accelerate mode.
207      * @return This object for method chaining.
208      */

209     public void setAccelerateModeEnabled(Boolean accelerateModeEnabled) {
210         this.accelerateModeEnabled = accelerateModeEnabled;
211     }
212
213     /**
214      * <p>Configures the client to use S3 accelerate endpoint for all requests.</p>
215      *
216      * <p>A bucket by default cannot be accessed in accelerate mode. If you wish to do so, you need
217      * to enable the accelerate configuration for the bucket in advance. To enable accelerate mode
218      * see {@link com.amazonaws.services.s3.AmazonS3Client#setBucketAccelerateConfiguration(com.amazonaws.services.s3.model.SetBucketAccelerateConfigurationRequest)}.
219      * </p>
220      *
221      * @param accelerateModeEnabled True to enable accelerate mode.
222      * @return This object for method chaining.
223      */

224     public Subclass withAccelerateModeEnabled(Boolean accelerateModeEnabled) {
225         setAccelerateModeEnabled(accelerateModeEnabled);
226         return getSubclass();
227     }
228
229     /**
230      * <p>Enables accelerate mode on clients built with the builder.</p>
231      *
232      * <p>A bucket by default cannot be accessed in accelerate mode. If you wish to do so, you need
233      * to enable the accelerate configuration for the bucket in advance. To enable accelerate mode
234      * see {@link com.amazonaws.services.s3.AmazonS3Client#setBucketAccelerateConfiguration(com.amazonaws.services.s3.model.SetBucketAccelerateConfigurationRequest)}.
235      * </p>
236      *
237      * @return This object for method chaining.
238      */

239     public Subclass enableAccelerateMode() {
240         setAccelerateModeEnabled(Boolean.TRUE);
241         return getSubclass();
242     }
243
244     /**
245      * @return The current setting for payload signing configured in the builder.
246      */

247     public Boolean isPayloadSigningEnabled() {
248         return payloadSigningEnabled;
249     }
250
251     /**
252      * <p>Configures the client to sign payloads in all situations.</p>
253      *
254      * <p>Payload signing is optional when chunked encoding is not used and requests are made
255      * against an HTTPS endpoint.  Under these conditions the client will by default opt to not sign
256      * payloads to optimize performance.  If this flag is set to true the client will instead always
257      * sign payloads.</p>
258      *
259      * <p><b>Note:</b> Payload signing can be expensive, particularly if transferring large payloads
260      * in a single chunk.  Enabling this option will result in a performance penalty.</p>
261      *
262      * @param payloadSigningEnabled True to explicitly enable payload signing in all situations
263      */

264     public void setPayloadSigningEnabled(Boolean payloadSigningEnabled) {
265         this.payloadSigningEnabled = payloadSigningEnabled;
266     }
267
268     /**
269      * <p>Configures the client to sign payloads in all situations.</p>
270      *
271      * <p>Payload signing is optional when chunked encoding is not used and requests are made
272      * against an HTTPS endpoint. Under these conditions the client will by default opt to not sign
273      * payloads to optimize performance.  If this flag is set to true the client will instead always
274      * sign payloads.</p>
275      *
276      * <p><b>Note:</b> Payload signing can be expensive, particularly if transferring large payloads
277      * in a single chunk. Enabling this option will result in a performance penalty.</p>
278      *
279      * @param payloadSigningEnabled True to explicitly enable payload signing in all situations
280      * @return This object for method chaining.
281      */

282     public Subclass withPayloadSigningEnabled(Boolean payloadSigningEnabled) {
283         setPayloadSigningEnabled(payloadSigningEnabled);
284         return getSubclass();
285     }
286
287     /**
288      * <p>Enables payload signing for all situations on clients built via this builder.</p>
289      *
290      * <p>Payload signing is optional when chunked encoding is not used and requests are made
291      * against an HTTPS endpoint.  Under these conditions the client will by default opt to not sign
292      * payloads to optimize performance.  If this flag is set to true the client will instead always
293      * sign payloads.</p>
294      *
295      * <p><b>Note:</b> Payload signing can be expensive, particularly if transferring large payloads
296      * in a single chunk.  Enabling this option will result in a performance penalty.</p>
297      *
298      * @return This object for method chaining.
299      */

300     public Subclass enablePayloadSigning() {
301         setPayloadSigningEnabled(Boolean.TRUE);
302         return getSubclass();
303     }
304
305     /**
306      * @return The current setting for dualstack mode configured in the builder.
307      */

308     public Boolean isDualstackEnabled() {
309         return dualstackEnabled;
310     }
311
312     /**
313      * <p>Configures the client to use Amazon S3 dualstack mode for all requests.</p>
314      *
315      * @param dualstackEnabled True to enable dualstack mode.
316      * @return This object for method chaining.
317      */

318     public void setDualstackEnabled(Boolean dualstackEnabled) {
319         this.dualstackEnabled = dualstackEnabled;
320     }
321
322     /**
323      * <p>Configures the client to use Amazon S3 dualstack mode for all requests.</p>
324      *
325      * @param dualstackEnabled True to enable dualstack mode.
326      * @return This object for method chaining.
327      */

328     public Subclass withDualstackEnabled(Boolean dualstackEnabled) {
329         setDualstackEnabled(dualstackEnabled);
330         return getSubclass();
331     }
332
333     /**
334      * <p>Enables dualstack mode on clients built with the builder.</p>
335
336      * @return This object for method chaining.
337      */

338     public Subclass enableDualstack() {
339         setDualstackEnabled(Boolean.TRUE);
340         return getSubclass();
341     }
342
343     /**
344      * @return Whether global bucket access is configured for clients generated by this builder.
345      * @see #setForceGlobalBucketAccessEnabled(Boolean)
346      */

347     public Boolean isForceGlobalBucketAccessEnabled() {
348         return forceGlobalBucketAccessEnabled;
349     }
350
351     /**
352      * <p>Configure whether global bucket access is enabled for clients generated by this builder.</p>
353      *
354      * <p>When global bucket access is enabled, the region to which a request is routed may differ from the region that
355      * is configured in {@link #setRegion(String)} in order to make the request succeed.</p>
356      *
357      * <p>
358      * The following behavior is <i>currently</i> used when this mode is enabled:
359      * <ol>
360      *     <li>All requests that do not act on an existing bucket (for example, {@link AmazonS3Client#createBucket(String)})
361      *     will be routed to the region configured by {@link #setRegion(String)}, unless the region is manually overridden
362      *     with {@link CreateBucketRequest#setRegion(String)}, in which case the request will be routed to the region
363      *     configured in the request.</li>
364      *     <li>The first time a request is made that references an existing bucket (for example,
365      *     {@link AmazonS3Client#putObject(PutObjectRequest)}) a request will be made to the region configured by
366      *     {@link #setRegion(String)} to determine the region in which the bucket was created. This location may be
367      *     cached in the client for subsequent requests acting on that same bucket.</li>
368      * </ol>
369      * </p>
370      *
371      * <p>Enabling this mode has several drawbacks, because it has the potential to increase latency in the event that
372      * the location of the bucket is physically far from the location from which the request was invoked. For this
373      * reason, it is strongly advised when possible to know the location of your buckets and create a region-specific
374      * client to access that bucket.</p>
375      *
376      * @param forceGlobalBucketAccessEnabled Whether global bucket access should be enabled.
377      */

378     public void setForceGlobalBucketAccessEnabled(Boolean forceGlobalBucketAccessEnabled) {
379         this.forceGlobalBucketAccessEnabled = forceGlobalBucketAccessEnabled;
380     }
381
382     /**
383      * <p>Configure whether global bucket access is enabled for clients generated by this builder.</p>
384      *
385      * @see #setForceGlobalBucketAccessEnabled(Boolean)
386      * @param forceGlobalBucketAccessEnabled Whether global bucket access should be enabled.
387      * @return This object for method chaining.
388      */

389     public Subclass withForceGlobalBucketAccessEnabled(Boolean forceGlobalBucketAccessEnabled) {
390         setForceGlobalBucketAccessEnabled(forceGlobalBucketAccessEnabled);
391         return getSubclass();
392     }
393
394     /**
395      * <p>Enable global bucket access for clients generated by this builder.</p>
396      *
397      * @see #setForceGlobalBucketAccessEnabled(Boolean)
398      * @return This object for method chaining.
399      */

400     public Subclass enableForceGlobalBucketAccess() {
401         setForceGlobalBucketAccessEnabled(Boolean.TRUE);
402         return getSubclass();
403     }
404
405     /**
406      * @return The current setting for useArnRegion mode configured in the builder.
407      */

408     public Boolean isUseArnRegionEnabled() {
409         return useArnRegionEnabled;
410     }
411
412     /**
413      * <p>Enables using the region from ARNs on clients built with the builder.</p>
414
415      * @return This object for method chaining.
416      */

417     public Subclass enableUseArnRegion() {
418         this.useArnRegionEnabled = true;
419         return getSubclass();
420     }
421
422     /**
423      * @return Whether us-east-1 should resolve to its regional endpoint or the default global endpoint.
424      * @see #setRegionalUsEast1EndpointEnabled(Boolean)
425      */

426     public Boolean isRegionalUsEast1EndpointEnabled() {
427         return regionalUsEast1EndpointEnabled;
428     }
429
430     /**
431      * <p>Configures the client to resolve region us-east-1 region to its regional endpoint instead of the
432      * global endpoint for all requests.</p>
433      *
434      * <p>The default value for this value is false, configuring this region resolve to the global s3 endpoint.</p>
435      *
436      * <p>
437      * There are three ways to enable this option. In order of precedence:
438      * <ol>
439      *     <li>Configuring the S3 client directly through this builder,
440      *     using {@link #setRegionalUsEast1EndpointEnabled(Boolean)}</li>
441      *     <li>Setting the environment variable AWS_S3_US_EAST_1_REGIONAL_ENDPOINT to <i>regional</i></li>
442      *     <li>Setting the shared config/profile file option s3_us_east_1_regional_endpoint <i>regional</i></li>
443      * </ol>
444      * Environment variable options override config values and direct configurations override environment variable
445      * settings. The accepted values for environment variable and config option are <i>regional</i> and <i>legacy</i>.
446      * Setting the values to <i>legacy</i> does not affect any change in behavior unless the intention is for the
447      * environment variable to override a regional setting in the config file.
448      * </p>
449      *
450      * @param regionalUsEast1EndpointEnabled True to enable us-east-1 regional mode.
451      * @return This object for method chaining.
452      */

453     public void setRegionalUsEast1EndpointEnabled(Boolean regionalUsEast1EndpointEnabled) {
454         this.regionalUsEast1EndpointEnabled = regionalUsEast1EndpointEnabled;
455     }
456
457     /**
458      * <p>Configures the client to resolve region us-east-1 region to its regional endpoint instead of the
459      * global endpoint for all requests.</p>
460      *
461      * @param regionalUsEast1EndpointEnabled True to enable us-east-1 regional mode.
462      * @return This object for method chaining.
463      * @see #setRegionalUsEast1EndpointEnabled(Boolean)
464      */

465     public Subclass withRegionalUsEast1EndpointEnabled(Boolean regionalUsEast1EndpointEnabled) {
466         setRegionalUsEast1EndpointEnabled(regionalUsEast1EndpointEnabled);
467         return getSubclass();
468     }
469
470     /**
471      * <p>Enables us-east-1 regional mode on clients built with the builder.</p>
472
473      * @return This object for method chaining.
474      */

475     public Subclass enableRegionalUsEast1Endpoint() {
476         setRegionalUsEast1EndpointEnabled(Boolean.TRUE);
477         return getSubclass();
478     }
479
480
481     protected S3ClientOptions resolveS3ClientOptions() {
482         final S3ClientOptions.Builder builder = S3ClientOptions.builder();
483         if (Boolean.TRUE.equals(this.chunkedEncodingDisabled)) {
484             builder.disableChunkedEncoding();
485         }
486         if (this.payloadSigningEnabled != null) {
487             builder.setPayloadSigningEnabled(this.payloadSigningEnabled);
488         }
489         if (this.accelerateModeEnabled != null) {
490             builder.setAccelerateModeEnabled(this.accelerateModeEnabled);
491         }
492         if (this.pathStyleAccessEnabled != null) {
493             builder.setPathStyleAccess(this.pathStyleAccessEnabled);
494         }
495         if(Boolean.TRUE.equals(this.dualstackEnabled)) {
496             builder.enableDualstack();
497         }
498         if(Boolean.TRUE.equals(this.forceGlobalBucketAccessEnabled)) {
499             builder.enableForceGlobalBucketAccess();
500         }
501         if(Boolean.TRUE.equals(this.useArnRegionEnabled)) {
502             builder.enableUseArnRegion();
503         }
504         if(Boolean.TRUE.equals(this.regionalUsEast1EndpointEnabled)) {
505             builder.enableRegionalUsEast1Endpoint();
506         }
507         return builder.build();
508     }
509 }
510