• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.core.client.config;
17 
18 import static software.amazon.awssdk.core.client.config.SdkClientOption.ENDPOINT_OVERRIDDEN;
19 import static software.amazon.awssdk.core.client.config.SdkClientOption.SIGNER_OVERRIDDEN;
20 
21 import java.util.Map;
22 import java.util.function.Consumer;
23 import java.util.function.Supplier;
24 import software.amazon.awssdk.annotations.SdkProtectedApi;
25 import software.amazon.awssdk.core.internal.SdkInternalTestAdvancedClientOption;
26 import software.amazon.awssdk.core.signer.Signer;
27 import software.amazon.awssdk.utils.AttributeMap;
28 import software.amazon.awssdk.utils.SdkAutoCloseable;
29 import software.amazon.awssdk.utils.ToString;
30 import software.amazon.awssdk.utils.builder.CopyableBuilder;
31 import software.amazon.awssdk.utils.builder.ToCopyableBuilder;
32 
33 /**
34  * A collection of configuration that is required by an AWS client in order to operate.
35  *
36  * Configuration can be set via {@link SdkClientConfiguration.Builder#option(ClientOption, Object)} and checked via
37  * {@link SdkClientConfiguration#option(ClientOption)}.
38  *
39  * This configuration can be merged with other configuration using {@link SdkClientConfiguration#merge}.
40  *
41  * This configuration object can be {@link #close()}d to release all closeable resources configured within it.
42  */
43 @SdkProtectedApi
44 public final class SdkClientConfiguration
45         implements ToCopyableBuilder<SdkClientConfiguration.Builder, SdkClientConfiguration>, SdkAutoCloseable {
46     private final AttributeMap attributes;
47 
SdkClientConfiguration(AttributeMap attributes)48     private SdkClientConfiguration(AttributeMap attributes) {
49         this.attributes = attributes;
50     }
51 
52     /**
53      * Create a builder for a {@link SdkClientConfiguration}.
54      */
builder()55     public static SdkClientConfiguration.Builder builder() {
56         return new Builder(AttributeMap.builder());
57     }
58 
59     /**
60      * Create a {@link SdkClientConfiguration} from the provided {@link ClientOverrideConfiguration}. This copies the
61      * properties out of the configuration and ensures that _OVERRIDDEN properties are properly set, like
62      * {@link SdkClientOption#SIGNER_OVERRIDDEN}.
63      */
fromOverrideConfiguration(ClientOverrideConfiguration configuration)64     public static SdkClientConfiguration fromOverrideConfiguration(ClientOverrideConfiguration configuration) {
65         SdkClientConfiguration result = configuration.asSdkClientConfiguration();
66 
67         Boolean endpointOverriddenOverride = result.option(SdkInternalTestAdvancedClientOption.ENDPOINT_OVERRIDDEN_OVERRIDE);
68         Signer signerFromOverride = result.option(SdkAdvancedClientOption.SIGNER);
69 
70         if (endpointOverriddenOverride == null && signerFromOverride == null) {
71             return result;
72         }
73 
74         SdkClientConfiguration.Builder resultBuilder = result.toBuilder();
75         if (signerFromOverride != null) {
76             resultBuilder.option(SIGNER_OVERRIDDEN, true);
77         }
78         if (endpointOverriddenOverride != null) {
79             resultBuilder.option(ENDPOINT_OVERRIDDEN, endpointOverriddenOverride);
80         }
81         return resultBuilder.build();
82     }
83 
84     /**
85      * Retrieve the value of a specific option.
86      */
option(ClientOption<T> option)87     public <T> T option(ClientOption<T> option) {
88         return attributes.get(option);
89     }
90 
91     /**
92      * Create a {@link ClientOverrideConfiguration} using the values currently in this configuration.
93      */
asOverrideConfiguration()94     public ClientOverrideConfiguration asOverrideConfiguration() {
95         return new ClientOverrideConfiguration.DefaultBuilder(toBuilder()).build();
96     }
97 
98     /**
99      * Merge this configuration with another configuration, where this configuration's values take precedence.
100      */
merge(SdkClientConfiguration configuration)101     public SdkClientConfiguration merge(SdkClientConfiguration configuration) {
102         return new SdkClientConfiguration(attributes.merge(configuration.attributes));
103     }
104 
merge(Consumer<SdkClientConfiguration.Builder> configuration)105     public SdkClientConfiguration merge(Consumer<SdkClientConfiguration.Builder> configuration) {
106         return merge(builder().applyMutation(configuration).build());
107     }
108 
109     @Override
toString()110     public String toString() {
111         return ToString.builder("SdkClientConfiguration")
112                        .add("attributes", attributes)
113                        .build();
114     }
115 
116     @Override
toBuilder()117     public Builder toBuilder() {
118         return new Builder(attributes.toBuilder());
119     }
120 
121     /**
122      * Close this configuration, which closes all closeable attributes.
123      */
124     @Override
close()125     public void close() {
126         attributes.close();
127     }
128 
129     @Override
equals(Object o)130     public boolean equals(Object o) {
131         if (this == o) {
132             return true;
133         }
134         if (o == null || getClass() != o.getClass()) {
135             return false;
136         }
137 
138         SdkClientConfiguration that = (SdkClientConfiguration) o;
139 
140         return attributes.equals(that.attributes);
141     }
142 
143     @Override
hashCode()144     public int hashCode() {
145         return attributes.hashCode();
146     }
147 
148     public static final class Builder implements CopyableBuilder<Builder, SdkClientConfiguration> {
149         private final AttributeMap.Builder attributes;
150 
Builder(AttributeMap.Builder attributes)151         private Builder(AttributeMap.Builder attributes) {
152             this.attributes = attributes;
153         }
154 
155         /**
156          * Create a {@link ClientOverrideConfiguration.Builder} using the values currently in this builder.
157          */
asOverrideConfigurationBuilder()158         public ClientOverrideConfiguration.Builder asOverrideConfigurationBuilder() {
159             return new ClientOverrideConfiguration.DefaultBuilder(this);
160         }
161 
162         /**
163          * Configure the value of a specific option.
164          */
option(ClientOption<T> option, T value)165         public <T> Builder option(ClientOption<T> option, T value) {
166             this.attributes.put(option, value);
167             return this;
168         }
169 
170         /**
171          * Add a mapping between the provided option and value provider.
172          *
173          * The lazy value will only be resolved when the value is needed. During resolution, the lazy value is provided with a
174          * value reader. The value reader will fail if the reader attempts to read its own value (directly, or indirectly
175          * through other lazy values).
176          *
177          * If a value is updated that a lazy value is depended on, the lazy value will be re-resolved the next time the lazy
178          * value is accessed.
179          */
lazyOption(ClientOption<T> option, AttributeMap.LazyValue<T> lazyValue)180         public <T> Builder lazyOption(ClientOption<T> option, AttributeMap.LazyValue<T> lazyValue) {
181             this.attributes.putLazy(option, lazyValue);
182             return this;
183         }
184 
185         /**
186          * Equivalent to {@link #lazyOption(ClientOption, AttributeMap.LazyValue)}, but does not assign the value if there is
187          * already a non-null value assigned for the provided option.
188          */
lazyOptionIfAbsent(ClientOption<T> option, AttributeMap.LazyValue<T> lazyValue)189         public <T> Builder lazyOptionIfAbsent(ClientOption<T> option, AttributeMap.LazyValue<T> lazyValue) {
190             this.attributes.putLazyIfAbsent(option, lazyValue);
191             return this;
192         }
193 
194         /**
195          * Retrieve the value of a specific option.
196          */
option(ClientOption<T> option)197         public <T> T option(ClientOption<T> option) {
198             return this.attributes.get(option);
199         }
200 
201         /**
202          * Add a mapping between the provided key and value, if the current value for the option is null. Returns the value.
203          */
computeOptionIfAbsent(ClientOption<T> option, Supplier<T> valueSupplier)204         public <T> T computeOptionIfAbsent(ClientOption<T> option, Supplier<T> valueSupplier) {
205             return this.attributes.computeIfAbsent(option, valueSupplier);
206         }
207 
208         /**
209          * Adds all the options from the map provided. This is not type safe, and will throw an exception during creation if
210          * a value in the map is not of the correct type for its option.
211          */
putAll(Map<? extends ClientOption<?>, ?> options)212         public Builder putAll(Map<? extends ClientOption<?>, ?> options) {
213             this.attributes.putAll(options);
214             return this;
215         }
216 
217         /**
218          * Put all of the attributes from the provided override configuration into this one.
219          */
putAll(ClientOverrideConfiguration configuration)220         public Builder putAll(ClientOverrideConfiguration configuration) {
221             this.attributes.putAll(fromOverrideConfiguration(configuration).attributes);
222             return this;
223         }
224 
225         @Override
copy()226         public Builder copy() {
227             return new Builder(attributes.copy());
228         }
229 
230         @Override
build()231         public SdkClientConfiguration build() {
232             return new SdkClientConfiguration(attributes.build());
233         }
234     }
235 }
236