| /* | |
| * Copyright 2012-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 com.amazonaws.auth; | |
| import java.util.LinkedList; | |
| import java.util.List; | |
| import org.apache.commons.logging.Log; | |
| import org.apache.commons.logging.LogFactory; | |
| import com.amazonaws.SdkClientException; | |
| /** | |
| * {@link AWSCredentialsProvider} implementation that chains together multiple | |
| * credentials providers. When a caller first requests credentials from this provider, | |
| * it calls all the providers in the chain, in the original order specified, | |
| * until one can provide credentials, and then returns those credentials. If all | |
| * of the credential providers in the chain have been called, and none of them | |
| * can provide credentials, then this class will throw an exception indicated | |
| * that no credentials are available. | |
| * <p> | |
| * By default, this class will remember the first credentials provider in the chain | |
| * that was able to provide credentials, and will continue to use that provider when | |
| * credentials are requested in the future, instead of traversing the chain each time. | |
| * This behavior can be controlled through the {@link #setReuseLastProvider(boolean)} method. | |
| */ | |
| public class AWSCredentialsProviderChain implements AWSCredentialsProvider { | |
| private static final Log log = LogFactory.getLog(AWSCredentialsProviderChain.class); | |
| private final List<AWSCredentialsProvider> credentialsProviders = | |
| new LinkedList<AWSCredentialsProvider>(); | |
| private boolean reuseLastProvider = true; | |
| private AWSCredentialsProvider lastUsedProvider; | |
| /** | |
| * Constructs a new AWSCredentialsProviderChain with the specified credential providers. When | |
| * credentials are requested from this provider, it will call each of these credential providers | |
| * in the same order specified here until one of them returns AWS security credentials. | |
| * | |
| * @param credentialsProviders | |
| * The chain of credentials providers. | |
| */ | |
| public AWSCredentialsProviderChain(List<? extends AWSCredentialsProvider> credentialsProviders) { | |
| if (credentialsProviders == null || credentialsProviders.size() == 0) { | |
| throw new IllegalArgumentException("No credential providers specified"); | |
| } | |
| this.credentialsProviders.addAll(credentialsProviders); | |
| } | |
| /** | |
| * Constructs a new AWSCredentialsProviderChain with the specified credential providers. When | |
| * credentials are requested from this provider, it will call each of these credential providers | |
| * in the same order specified here until one of them returns AWS security credentials. | |
| * | |
| * @param credentialsProviders | |
| * The chain of credentials providers. | |
| */ | |
| public AWSCredentialsProviderChain(AWSCredentialsProvider... credentialsProviders) { | |
| if (credentialsProviders == null || credentialsProviders.length == 0) { | |
| throw new IllegalArgumentException("No credential providers specified"); | |
| } | |
| for (AWSCredentialsProvider provider : credentialsProviders) { | |
| this.credentialsProviders.add(provider); | |
| } | |
| } | |
| /** | |
| * Returns true if this chain will reuse the last successful credentials | |
| * provider for future credentials requests, otherwise, false if it will | |
| * search through the chain each time. | |
| * | |
| * @return True if this chain will reuse the last successful credentials | |
| * provider for future credentials requests. | |
| */ | |
| public boolean getReuseLastProvider() { | |
| return reuseLastProvider; | |
| } | |
| /** | |
| * Enables or disables caching of the last successful credentials provider | |
| * in this chain. Reusing the last successful credentials provider will | |
| * typically return credentials faster than searching through the chain. | |
| * | |
| * @param b | |
| * Whether to enable or disable reusing the last successful | |
| * credentials provider for future credentials requests instead | |
| * of searching through the whole chain. | |
| */ | |
| public void setReuseLastProvider(boolean b) { | |
| this.reuseLastProvider = b; | |
| } | |
| public AWSCredentials getCredentials() { | |
| if (reuseLastProvider && lastUsedProvider != null) { | |
| return lastUsedProvider.getCredentials(); | |
| } | |
| for (AWSCredentialsProvider provider : credentialsProviders) { | |
| try { | |
| AWSCredentials credentials = provider.getCredentials(); | |
| if (credentials.getAWSAccessKeyId() != null && | |
| credentials.getAWSSecretKey() != null) { | |
| log.debug("Loading credentials from " + provider.toString()); | |
| lastUsedProvider = provider; | |
| return credentials; | |
| } | |
| } catch (Exception e) { | |
| // Ignore any exceptions and move onto the next provider | |
| log.debug("Unable to load credentials from " + provider.toString() + | |
| ": " + e.getMessage()); | |
| } | |
| } | |
| throw new SdkClientException("Unable to load AWS credentials from any provider in the chain"); | |
| } | |
| public void refresh() { | |
| for (AWSCredentialsProvider provider : credentialsProviders) { | |
| provider.refresh(); | |
| } | |
| } | |
| } |