Skip to content

Commit 6b186a2

Browse files
authored
ProfileFileSupplier API changes, aggregating (#3558)
* Added methods for aggregating ProfileFile objects * Removed redundant logic, changelog entry * Removed redundant methods * Use compare and set to make thread safe
1 parent 33d4012 commit 6b186a2

File tree

5 files changed

+318
-52
lines changed

5 files changed

+318
-52
lines changed

core/auth/src/main/java/software/amazon/awssdk/auth/credentials/ProfileCredentialsProvider.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,9 @@ static final class BuilderImpl implements Builder {
225225

226226
@Override
227227
public Builder profileFile(ProfileFile profileFile) {
228-
return profileFile(ProfileFileSupplier.wrapIntoNullableSupplier(profileFile));
228+
return profileFile(Optional.ofNullable(profileFile)
229+
.map(ProfileFileSupplier::fixedProfileFile)
230+
.orElse(null));
229231
}
230232

231233
public void setProfileFile(ProfileFile profileFile) {

core/auth/src/test/java/software/amazon/awssdk/auth/credentials/ProfileCredentialsProviderTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ void resolveCredentials_presentProfileFileSupplier_returnsCredentials() {
193193

194194
ProfileCredentialsProvider provider =
195195
ProfileCredentialsProvider.builder()
196-
.profileFile(ProfileFileSupplier.reloadWhenModified(path))
196+
.profileFile(ProfileFileSupplier.reloadWhenModified(path, ProfileFile.Type.CREDENTIALS))
197197
.profileName("default")
198198
.build();
199199

core/profiles/src/main/java/software/amazon/awssdk/profiles/ProfileFileSupplier.java

Lines changed: 75 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@
1616
package software.amazon.awssdk.profiles;
1717

1818
import java.nio.file.Path;
19+
import java.util.Arrays;
1920
import java.util.Objects;
21+
import java.util.Optional;
22+
import java.util.concurrent.atomic.AtomicReference;
2023
import java.util.function.Supplier;
2124
import software.amazon.awssdk.annotations.SdkPublicApi;
2225
import software.amazon.awssdk.profiles.internal.ProfileFileRefresher;
@@ -36,21 +39,53 @@ public interface ProfileFileSupplier extends Supplier<ProfileFile>, SdkAutoClose
3639
default void close() {
3740
}
3841

42+
/**
43+
* Creates a {@link ProfileFileSupplier} capable of producing multiple profile objects by aggregating the default
44+
* credentials and configuration files as determined by {@link ProfileFileLocation#credentialsFileLocation()} abd
45+
* {@link ProfileFileLocation#configurationFileLocation()}. This supplier will return a new ProfileFile instance only once
46+
* either disk file has been modified. Multiple calls to the supplier while both disk files are unchanged will return the
47+
* same object.
48+
*
49+
* @return Implementation of {@link ProfileFileSupplier} that is capable of supplying a new aggregate profile when either file
50+
* has been modified.
51+
*/
52+
static ProfileFileSupplier defaultSupplier() {
53+
Optional<ProfileFileSupplier> credentialsSupplierOptional
54+
= ProfileFileLocation.credentialsFileLocation()
55+
.map(path -> reloadWhenModified(path, ProfileFile.Type.CREDENTIALS));
56+
57+
Optional<ProfileFileSupplier> configurationSupplierOptional
58+
= ProfileFileLocation.configurationFileLocation()
59+
.map(path -> reloadWhenModified(path, ProfileFile.Type.CONFIGURATION));
60+
61+
ProfileFileSupplier supplier = () -> null;
62+
if (credentialsSupplierOptional.isPresent() && configurationSupplierOptional.isPresent()) {
63+
supplier = aggregate(credentialsSupplierOptional.get(), configurationSupplierOptional.get());
64+
} else if (credentialsSupplierOptional.isPresent()) {
65+
supplier = credentialsSupplierOptional.get();
66+
} else if (configurationSupplierOptional.isPresent()) {
67+
supplier = configurationSupplierOptional.get();
68+
}
69+
70+
return supplier;
71+
}
72+
3973
/**
4074
* Creates a {@link ProfileFileSupplier} capable of producing multiple profile objects from a file. This supplier will
4175
* return a new ProfileFile instance only once the disk file has been modified. Multiple calls to the supplier while the
4276
* disk file is unchanged will return the same object.
4377
*
4478
* @param path Path to the file to read from.
79+
* @param type The type of file. See {@link ProfileFile.Type} for possible values.
4580
* @return Implementation of {@link ProfileFileSupplier} that is capable of supplying a new profile when the file
4681
* has been modified.
4782
*/
48-
static ProfileFileSupplier reloadWhenModified(Path path) {
83+
static ProfileFileSupplier reloadWhenModified(Path path, ProfileFile.Type type) {
4984
return new ProfileFileSupplier() {
5085

5186
final ProfileFile.Builder builder = ProfileFile.builder()
5287
.content(path)
53-
.type(ProfileFile.Type.CREDENTIALS);
88+
.type(type);
5489

5590
final ProfileFileRefresher refresher = ProfileFileRefresher.builder()
5691
.profileFile(builder::build)
@@ -69,21 +104,6 @@ public void close() {
69104
};
70105
}
71106

72-
/**
73-
* Creates a {@link ProfileFileSupplier} capable of producing a single profile object from a file.
74-
*
75-
* @param path Path to the file to read from.
76-
* @return Implementation of {@link ProfileFileSupplier} that is capable of supplying a single profile.
77-
*/
78-
static ProfileFileSupplier fixedProfileFile(Path path) {
79-
ProfileFile profileFile = ProfileFile.builder()
80-
.content(path)
81-
.type(ProfileFile.Type.CREDENTIALS)
82-
.build();
83-
84-
return () -> profileFile;
85-
}
86-
87107
/**
88108
* Creates a {@link ProfileFileSupplier} that produces an existing profile.
89109
*
@@ -95,14 +115,46 @@ static ProfileFileSupplier fixedProfileFile(ProfileFile profileFile) {
95115
}
96116

97117
/**
98-
* creates a {@link ProfileFileSupplier} that produces an existing non-null profile. If the given profile
99-
* is null, then the created supplier will also be null.
118+
* Creates a {@link ProfileFileSupplier} by combining the {@link ProfileFile} objects from two {@code ProfileFileSupplier}s.
119+
* Objects are passed into {@link ProfileFile.Aggregator}.
100120
*
101-
* @param profileFile Profile object to supply.
102-
* @return Implementation of {@link ProfileFileSupplier} that is capable of supplying a single profile.
121+
* @param suppliers Array of {@code ProfileFileSupplier} objects. {@code ProfileFile} objects are passed to
122+
* {@link ProfileFile.Aggregator#addFile(ProfileFile)} in the same argument order as the supplier that
123+
* generated it.
124+
* @return Implementation of {@link ProfileFileSupplier} aggregating results from the supplier objects.
103125
*/
104-
static ProfileFileSupplier wrapIntoNullableSupplier(ProfileFile profileFile) {
105-
return Objects.nonNull(profileFile) ? () -> profileFile : null;
126+
static ProfileFileSupplier aggregate(ProfileFileSupplier... suppliers) {
127+
128+
return new ProfileFileSupplier() {
129+
130+
final AtomicReference<ProfileFile> currentAggregateProfileFile = new AtomicReference<>();
131+
132+
@Override
133+
public ProfileFile get() {
134+
ProfileFile.Aggregator aggregator = ProfileFile.aggregator();
135+
for (ProfileFileSupplier supplier : suppliers) {
136+
aggregator.addFile(supplier.get());
137+
}
138+
139+
return refreshAndGetCurrentAggregate(aggregator);
140+
}
141+
142+
@Override
143+
public void close() {
144+
Arrays.stream(suppliers).forEach(ProfileFileSupplier::close);
145+
}
146+
147+
private ProfileFile refreshAndGetCurrentAggregate(ProfileFile.Aggregator aggregator) {
148+
ProfileFile current = currentAggregateProfileFile.get();
149+
ProfileFile next = aggregator.build();
150+
if (!Objects.equals(current, next)) {
151+
currentAggregateProfileFile.compareAndSet(current, next);
152+
}
153+
154+
return currentAggregateProfileFile.get();
155+
}
156+
157+
};
106158
}
107159

108160
}

core/profiles/src/main/java/software/amazon/awssdk/profiles/ProfileFileSupplierBuilder.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,20 +32,20 @@ final class ProfileFileSupplierBuilder {
3232
private Clock clock;
3333
private Consumer<ProfileFile> onProfileFileLoad;
3434

35-
public ProfileFileSupplierBuilder reloadWhenModified(Path path) {
35+
public ProfileFileSupplierBuilder reloadWhenModified(Path path, ProfileFile.Type type) {
3636
ProfileFile.Builder builder = ProfileFile.builder()
3737
.content(path)
38-
.type(ProfileFile.Type.CREDENTIALS);
38+
.type(type);
3939
this.profileFile = builder::build;
4040
this.profileFilePath = path;
4141
this.reloadingSupplier = true;
4242
return this;
4343
}
4444

45-
public ProfileFileSupplierBuilder fixedProfileFile(Path path) {
45+
public ProfileFileSupplierBuilder fixedProfileFile(Path path, ProfileFile.Type type) {
4646
return fixedProfileFile(ProfileFile.builder()
4747
.content(path)
48-
.type(ProfileFile.Type.CREDENTIALS)
48+
.type(type)
4949
.build());
5050
}
5151

0 commit comments

Comments
 (0)