Skip to content

Add missing CopyableBuilder interfaces and fixed buggy ones. #3267

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion build-tools/src/main/resources/findbugs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,8 @@

<FindbugsPlugin>
<Detector class="software.amazon.awssdk.buildtools.findbugs.DisallowMethodCall" speed="fast" />
<Detector class="software.amazon.awssdk.buildtools.findbugs.ToBuilderIsCorrect" speed="fast" />

<BugPattern abbrev="BM" type="SDK_BAD_METHOD_CALL" category="PERFORMANCE" />
</FindbugsPlugin>
<BugPattern abbrev="BTB" type="BAD_TO_BUILDER" category="BUG" />
</FindbugsPlugin>
11 changes: 9 additions & 2 deletions build-tools/src/main/resources/messages.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@
-->

<MessageCollection>

<Detector class="software.amazon.awssdk.buildtools.findbugs.DisallowMethodCall" >
<Details>This detector checks for method calls that are not allowed for use.</Details>
</Detector>
<Detector class="software.amazon.awssdk.buildtools.findbugs.ToBuilderIsCorrect" >
<Details>This detector checks for correct CopyableBuilder definition.</Details>
</Detector>

<BugPattern type="SDK_BAD_METHOD_CALL">
<ShortDescription>Bad method call</ShortDescription>
Expand All @@ -41,6 +43,11 @@
]]>
</Details>
</BugPattern>
<BugPattern type="BAD_TO_BUILDER">
<ShortDescription>Bad toBuilder implementation</ShortDescription>
<LongDescription>Bad toBuilder implementation. See the SpotBugs logs for problem details.</LongDescription>
<Details>Bad toBuilder implementation. See the SpotBugs logs for problem details.</Details>
</BugPattern>

<BugCode abbrev="BM">Bad method</BugCode>
<BugCode abbrev="BTB">Bad toBuilder implementation</BugCode>
</MessageCollection>
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

package software.amazon.awssdk.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Used to suppress certain fields from being considered in the spot-bugs rule for toBuilder(). This annotation must be
* attached to the toBuilder() method to function.
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.CLASS)
@SdkProtectedApi
public @interface ToBuilderIgnoreField {
/**
* Specify which fields to ignore in the to-builder spotbugs rule.
*/
String[] value();
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
import software.amazon.awssdk.utils.SdkAutoCloseable;
import software.amazon.awssdk.utils.ToString;
import software.amazon.awssdk.utils.Validate;
import software.amazon.awssdk.utils.builder.CopyableBuilder;
import software.amazon.awssdk.utils.builder.ToCopyableBuilder;

/**
* {@link AwsCredentialsProvider} implementation that chains together multiple credentials providers.
Expand All @@ -44,7 +46,10 @@
* providers in the chain that need to be closed.</p>
*/
@SdkPublicApi
public final class AwsCredentialsProviderChain implements AwsCredentialsProvider, SdkAutoCloseable {
public final class AwsCredentialsProviderChain
implements AwsCredentialsProvider,
SdkAutoCloseable,
ToCopyableBuilder<AwsCredentialsProviderChain.Builder, AwsCredentialsProviderChain> {
private static final Logger log = Logger.loggerFor(AwsCredentialsProviderChain.class);

private final List<AwsCredentialsProvider> credentialsProviders;
Expand Down Expand Up @@ -124,10 +129,15 @@ public String toString() {
.build();
}

@Override
public Builder toBuilder() {
return new BuilderImpl(this);
}

/**
* A builder for a {@link AwsCredentialsProviderChain} that allows controlling its behavior.
*/
public interface Builder {
public interface Builder extends CopyableBuilder<Builder, AwsCredentialsProviderChain> {

/**
* Controls whether the chain should reuse the last successful credentials provider in the chain. Reusing the last
Expand Down Expand Up @@ -163,6 +173,11 @@ private static final class BuilderImpl implements Builder {
private BuilderImpl() {
}

private BuilderImpl(AwsCredentialsProviderChain provider) {
this.reuseLastProviderEnabled = provider.reuseLastProviderEnabled;
this.credentialsProviders = provider.credentialsProviders;
}

@Override
public Builder reuseLastProviderEnabled(Boolean reuseLastProviderEnabled) {
this.reuseLastProviderEnabled = reuseLastProviderEnabled;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
import software.amazon.awssdk.utils.StringUtils;
import software.amazon.awssdk.utils.ToString;
import software.amazon.awssdk.utils.Validate;
import software.amazon.awssdk.utils.builder.CopyableBuilder;
import software.amazon.awssdk.utils.builder.ToCopyableBuilder;
import software.amazon.awssdk.utils.cache.CachedSupplier;
import software.amazon.awssdk.utils.cache.NonBlocking;
import software.amazon.awssdk.utils.cache.RefreshResult;
Expand All @@ -60,18 +62,26 @@
* Service (ECS)</a>
*/
@SdkPublicApi
public final class ContainerCredentialsProvider implements HttpCredentialsProvider {
public final class ContainerCredentialsProvider
implements HttpCredentialsProvider,
ToCopyableBuilder<ContainerCredentialsProvider.Builder, ContainerCredentialsProvider> {
private static final Set<String> ALLOWED_HOSTS = unmodifiableSet(new HashSet<>(Arrays.asList("localhost", "127.0.0.1")));

private final String endpoint;
private final HttpCredentialsLoader httpCredentialsLoader;
private final CachedSupplier<AwsCredentials> credentialsCache;

private final Boolean asyncCredentialUpdateEnabled;

private final String asyncThreadName;

/**
* @see #builder()
*/
private ContainerCredentialsProvider(BuilderImpl builder) {
this.endpoint = builder.endpoint;
this.asyncCredentialUpdateEnabled = builder.asyncCredentialUpdateEnabled;
this.asyncThreadName = builder.asyncThreadName;
this.httpCredentialsLoader = HttpCredentialsLoader.create();

if (Boolean.TRUE.equals(builder.asyncCredentialUpdateEnabled)) {
Expand Down Expand Up @@ -137,6 +147,11 @@ public void close() {
credentialsCache.close();
}

@Override
public Builder toBuilder() {
return new BuilderImpl(this);
}

static final class ContainerCredentialsEndpointProvider implements ResourcesEndpointProvider {
private final String endpoint;

Expand Down Expand Up @@ -209,18 +224,25 @@ private URI createGenericContainerUrl() {
/**
* A builder for creating a custom a {@link ContainerCredentialsProvider}.
*/
public interface Builder extends HttpCredentialsProvider.Builder<ContainerCredentialsProvider, Builder> {
public interface Builder extends HttpCredentialsProvider.Builder<ContainerCredentialsProvider, Builder>,
CopyableBuilder<Builder, ContainerCredentialsProvider> {
}

private static final class BuilderImpl implements Builder {
private String endpoint;
private Boolean asyncCredentialUpdateEnabled;
private String asyncThreadName;

BuilderImpl() {
private BuilderImpl() {
asyncThreadName("container-credentials-provider");
}

private BuilderImpl(ContainerCredentialsProvider credentialsProvider) {
this.endpoint = credentialsProvider.endpoint;
this.asyncCredentialUpdateEnabled = credentialsProvider.asyncCredentialUpdateEnabled;
this.asyncThreadName = credentialsProvider.asyncThreadName;
}

@Override
public Builder endpoint(String endpoint) {
this.endpoint = endpoint;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
import software.amazon.awssdk.profiles.ProfileFile;
import software.amazon.awssdk.utils.SdkAutoCloseable;
import software.amazon.awssdk.utils.ToString;
import software.amazon.awssdk.utils.builder.CopyableBuilder;
import software.amazon.awssdk.utils.builder.ToCopyableBuilder;

/**
* AWS credentials provider chain that looks for credentials in this order:
Expand All @@ -41,16 +43,30 @@
* @see InstanceProfileCredentialsProvider
*/
@SdkPublicApi
public final class DefaultCredentialsProvider implements AwsCredentialsProvider, SdkAutoCloseable {
public final class DefaultCredentialsProvider
implements AwsCredentialsProvider, SdkAutoCloseable,
ToCopyableBuilder<DefaultCredentialsProvider.Builder, DefaultCredentialsProvider> {

private static final DefaultCredentialsProvider DEFAULT_CREDENTIALS_PROVIDER = new DefaultCredentialsProvider(builder());

private final LazyAwsCredentialsProvider providerChain;

private final ProfileFile profileFile;

private final String profileName;

private final Boolean reuseLastProviderEnabled;

private final Boolean asyncCredentialUpdateEnabled;

/**
* @see #builder()
*/
private DefaultCredentialsProvider(Builder builder) {
this.profileFile = builder.profileFile;
this.profileName = builder.profileName;
this.reuseLastProviderEnabled = builder.reuseLastProviderEnabled;
this.asyncCredentialUpdateEnabled = builder.asyncCredentialUpdateEnabled;
this.providerChain = createChain(builder);
}

Expand Down Expand Up @@ -119,10 +135,15 @@ public String toString() {
.build();
}

@Override
public Builder toBuilder() {
return new Builder(this);
}

/**
* Configuration that defines the {@link DefaultCredentialsProvider}'s behavior.
*/
public static final class Builder {
public static final class Builder implements CopyableBuilder<Builder, DefaultCredentialsProvider> {
private ProfileFile profileFile;
private String profileName;
private Boolean reuseLastProviderEnabled = true;
Expand All @@ -134,6 +155,13 @@ public static final class Builder {
private Builder() {
}

private Builder(DefaultCredentialsProvider credentialsProvider) {
this.profileFile = credentialsProvider.profileFile;
this.profileName = credentialsProvider.profileName;
this.reuseLastProviderEnabled = credentialsProvider.reuseLastProviderEnabled;
this.asyncCredentialUpdateEnabled = credentialsProvider.asyncCredentialUpdateEnabled;
}

public Builder profileFile(ProfileFile profileFile) {
this.profileFile = profileFile;
return this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@
import software.amazon.awssdk.utils.Logger;
import software.amazon.awssdk.utils.ToString;
import software.amazon.awssdk.utils.Validate;
import software.amazon.awssdk.utils.builder.CopyableBuilder;
import software.amazon.awssdk.utils.builder.ToCopyableBuilder;
import software.amazon.awssdk.utils.cache.CachedSupplier;
import software.amazon.awssdk.utils.cache.NonBlocking;
import software.amazon.awssdk.utils.cache.RefreshResult;
Expand All @@ -54,7 +56,9 @@
* credentials from EC2 metadata service and will return null.
*/
@SdkPublicApi
public final class InstanceProfileCredentialsProvider implements HttpCredentialsProvider {
public final class InstanceProfileCredentialsProvider
implements HttpCredentialsProvider,
ToCopyableBuilder<InstanceProfileCredentialsProvider.Builder, InstanceProfileCredentialsProvider> {
private static final Logger log = Logger.loggerFor(InstanceProfileCredentialsProvider.class);
private static final String EC2_METADATA_TOKEN_HEADER = "x-aws-ec2-metadata-token";

Expand All @@ -69,6 +73,14 @@ public final class InstanceProfileCredentialsProvider implements HttpCredentials
private final HttpCredentialsLoader httpCredentialsLoader;
private final CachedSupplier<AwsCredentials> credentialsCache;

private final Boolean asyncCredentialUpdateEnabled;

private final String asyncThreadName;

private final ProfileFile profileFile;

private final String profileName;

private volatile LoadedCredentials cachedCredentials;

/**
Expand All @@ -77,6 +89,11 @@ public final class InstanceProfileCredentialsProvider implements HttpCredentials
private InstanceProfileCredentialsProvider(BuilderImpl builder) {
this.clock = builder.clock;
this.endpoint = builder.endpoint;
this.asyncCredentialUpdateEnabled = builder.asyncCredentialUpdateEnabled;
this.asyncThreadName = builder.asyncThreadName;
this.profileFile = builder.profileFile;
this.profileName = builder.profileName;

this.httpCredentialsLoader = HttpCredentialsLoader.create();
this.configProvider =
Ec2MetadataConfigProvider.builder()
Expand Down Expand Up @@ -275,10 +292,16 @@ private Map<String, String> getTokenHeaders(String metadataToken) {
return Collections.singletonMap(EC2_METADATA_TOKEN_HEADER, metadataToken);
}

@Override
public Builder toBuilder() {
return new BuilderImpl(this);
}

/**
* A builder for creating a custom a {@link InstanceProfileCredentialsProvider}.
*/
public interface Builder extends HttpCredentialsProvider.Builder<InstanceProfileCredentialsProvider, Builder> {
public interface Builder extends HttpCredentialsProvider.Builder<InstanceProfileCredentialsProvider, Builder>,
CopyableBuilder<Builder, InstanceProfileCredentialsProvider> {
/**
* Configure the profile file used for loading IMDS-related configuration, like the endpoint mode (IPv4 vs IPv6).
*
Expand Down Expand Up @@ -312,6 +335,15 @@ private BuilderImpl() {
asyncThreadName("instance-profile-credentials-provider");
}

private BuilderImpl(InstanceProfileCredentialsProvider provider) {
this.clock = provider.clock;
this.endpoint = provider.endpoint;
this.asyncCredentialUpdateEnabled = provider.asyncCredentialUpdateEnabled;
this.asyncThreadName = provider.asyncThreadName;
this.profileFile = provider.profileFile;
this.profileName = provider.profileName;
}

Builder clock(Clock clock) {
this.clock = clock;
return this;
Expand Down
Loading