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