All Downloads are FREE. Search and download functionalities are using the official Maven repository.

software.amazon.awssdk.profiles.ProfileFile Maven / Gradle / Ivy

Go to download

A single bundled dependency that includes all service and dependent JARs with third-party libraries relocated to different namespaces.

There is a newer version: 2.5.20
Show newest version
/*
 * Copyright 2010-2018 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.profiles;

import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Optional;
import software.amazon.awssdk.annotations.SdkPublicApi;
import software.amazon.awssdk.profiles.internal.ProfileFileReader;
import software.amazon.awssdk.utils.FunctionalUtils;
import software.amazon.awssdk.utils.IoUtils;
import software.amazon.awssdk.utils.ToString;
import software.amazon.awssdk.utils.Validate;
import software.amazon.awssdk.utils.builder.SdkBuilder;

/**
 * Provides programmatic access to the contents of an AWS configuration profile file.
 *
 * AWS configuration profiles allow you to share multiple sets of AWS security credentials between different tools such as the
 * AWS SDK for Java and the AWS CLI.
 *
 * 

* For more information on setting up AWS configuration profiles, see: * http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html * *

* A profile file can be created with {@link #builder()} and merged with other profiles files with {@link #aggregator()}. By * default, the SDK will use the {@link #defaultProfileFile()} when that behavior hasn't been explicitly overridden. */ @SdkPublicApi public final class ProfileFile { private final Map profiles; /** * @see #builder() */ private ProfileFile(Map> rawProfiles) { Validate.paramNotNull(rawProfiles, "rawProfiles"); this.profiles = Collections.unmodifiableMap(convertToProfilesMap(rawProfiles)); } /** * Create a builder for a {@link ProfileFile}. */ public static Builder builder() { return new BuilderImpl(); } /** * Create a builder that can merge multiple {@link ProfileFile}s together. */ public static Aggregator aggregator() { return new Aggregator(); } /** * Get the default profile file, using the credentials file from "~/.aws/credentials", the config file from "~/.aws/config" * and the "default" profile. This default behavior can be customized using the * {@link ProfileFileSystemSetting#AWS_SHARED_CREDENTIALS_FILE}, {@link ProfileFileSystemSetting#AWS_CONFIG_FILE} and * {@link ProfileFileSystemSetting#AWS_PROFILE} settings or by specifying a different profile file and profile name */ public static ProfileFile defaultProfileFile() { return ProfileFile.aggregator() .applyMutation(ProfileFile::addCredentialsFile) .applyMutation(ProfileFile::addConfigFile) .build(); } /** * Retrieve the profile from this file with the given name. * * @param profileName The name of the profile that should be retrieved from this file. * @return The profile, if available. */ public Optional profile(String profileName) { return Optional.ofNullable(profiles.get(profileName)); } /** * Retrieve an unmodifiable collection including all of the profiles in this file. * @return An unmodifiable collection of the profiles in this file, keyed by profile name. */ public Map profiles() { return profiles; } @Override public String toString() { return ToString.builder("ProfileFile") .add("profiles", profiles.values()) .build(); } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } final ProfileFile that = (ProfileFile) o; return Objects.equals(profiles, that.profiles); } @Override public int hashCode() { return Objects.hashCode(profiles()); } private static void addCredentialsFile(ProfileFile.Aggregator builder) { ProfileFileLocation.credentialsFileLocation() .ifPresent(l -> builder.addFile(ProfileFile.builder() .content(l) .type(ProfileFile.Type.CREDENTIALS) .build())); } private static void addConfigFile(ProfileFile.Aggregator builder) { ProfileFileLocation.configurationFileLocation() .ifPresent(l -> builder.addFile(ProfileFile.builder() .content(l) .type(ProfileFile.Type.CONFIGURATION) .build())); } /** * Convert the sorted map of profile properties into a sorted list of profiles. */ private Map convertToProfilesMap(Map> sortedProfiles) { Map result = new LinkedHashMap<>(); for (Entry> rawProfile : sortedProfiles.entrySet()) { Profile profile = Profile.builder() .name(rawProfile.getKey()) .properties(rawProfile.getValue()) .build(); result.put(profile.name(), profile); } return result; } /** * The supported types of profile files. The type of profile determines the way in which it is parsed. */ public enum Type { /** * A configuration profile file, typically located at ~/.aws/config, that expects all profile names (except the default * profile) to be prefixed with "profile ". Any non-default profiles without this prefix will be ignored. */ CONFIGURATION, /** * A credentials profile file, typically located at ~/.aws/credentials, that expects all profile name to have no * "profile " prefix. Any profiles with a profile prefix will be ignored. */ CREDENTIALS } /** * A builder for a {@link ProfileFile}. {@link #content(Path)} (or {@link #content(InputStream)}) and {@link #type(Type)} are * required fields. */ public interface Builder extends SdkBuilder { /** * Configure the content of the profile file. This stream will be read from and then closed when {@link #build()} is * invoked. */ Builder content(InputStream contentStream); /** * Configure the location from which the profile file should be loaded. */ Builder content(Path contentLocation); /** * Configure the {@link Type} of file that should be loaded. */ Builder type(Type type); @Override ProfileFile build(); } private static final class BuilderImpl implements Builder { private InputStream content; private Path contentLocation; private Type type; private BuilderImpl() {} @Override public Builder content(InputStream contentStream) { this.contentLocation = null; this.content = contentStream; return this; } public void setContent(InputStream contentStream) { content(contentStream); } @Override public Builder content(Path contentLocation) { Validate.paramNotNull(contentLocation, "profileLocation"); Validate.validState(contentLocation.toFile().exists(), "Profile file '%s' does not exist.", contentLocation); this.content = null; this.contentLocation = contentLocation; return this; } public void setContentLocation(Path contentLocation) { content(contentLocation); } /** * Configure the {@link Type} of file that should be loaded. */ public Builder type(Type type) { this.type = type; return this; } public void setType(Type type) { type(type); } @Override public ProfileFile build() { InputStream stream = content != null ? content : FunctionalUtils.invokeSafely(() -> Files.newInputStream(contentLocation)); Validate.paramNotNull(type, "type"); Validate.paramNotNull(stream, "content"); try { return new ProfileFile(ProfileFileReader.parseFile(stream, type)); } finally { IoUtils.closeQuietly(stream, null); } } } /** * A mechanism for merging multiple {@link ProfileFile}s together into a single file. This will merge their profiles and * properties together. */ public static final class Aggregator implements SdkBuilder { private List files = new ArrayList<>(); /** * Add a file to be aggregated. In the event that there is a duplicate profile/property pair in the files, files added * earliest to this aggregator will take precedence, dropping the duplicated properties in the later files. */ public Aggregator addFile(ProfileFile file) { files.add(file); return this; } @Override public ProfileFile build() { Map> aggregateRawProfiles = new LinkedHashMap<>(); for (int i = files.size() - 1; i >= 0; --i) { addToAggregate(aggregateRawProfiles, files.get(i)); } return new ProfileFile(aggregateRawProfiles); } private void addToAggregate(Map> aggregateRawProfiles, ProfileFile file) { Map profiles = file.profiles(); for (Entry profile : profiles.entrySet()) { aggregateRawProfiles.compute(profile.getKey(), (k, current) -> { if (current == null) { return new HashMap<>(profile.getValue().properties()); } else { current.putAll(profile.getValue().properties()); return current; } }); } } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy