com.amazonaws.internal.config.InternalConfig.java Source code

Java tutorial

Introduction

Here is the source code for com.amazonaws.internal.config.InternalConfig.java

Source

/*
 * Copyright 2010-2014 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.internal.config;

import java.io.IOException;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.annotation.Immutable;

import com.amazonaws.regions.Regions;
import com.amazonaws.util.ClassLoaderHelper;
import com.amazonaws.util.json.Jackson;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;

/**
 * Internal configuration for the AWS Java SDK.
 */
@Immutable
public class InternalConfig {

    private static final Log log = LogFactory.getLog(InternalConfig.class);

    static final String DEFAULT_CONFIG_RESOURCE = "awssdk_config_default.json";
    static final String CONFIG_OVERRIDE_RESOURCE = "awssdk_config_override.json";
    private static final String SERVICE_REGION_DELIMITOR = "/";

    private final SignerConfig defaultSignerConfig;
    private final Map<String, SignerConfig> serviceRegionSigners;
    private final Map<String, SignerConfig> regionSigners;
    private final Map<String, SignerConfig> serviceSigners;
    private final Map<String, HttpClientConfig> httpClients;

    private final String userAgentTemplate;

    /**
     * @param defaults default configuration
     * @param override override configuration
     */
    InternalConfig(InternalConfigJsonHelper defaults, InternalConfigJsonHelper override) {
        SignerConfigJsonHelper scb = defaults.getDefaultSigner();
        this.defaultSignerConfig = scb == null ? null : scb.build();

        regionSigners = mergeSignerMap(defaults.getRegionSigners(), override.getRegionSigners(), "region");
        serviceSigners = mergeSignerMap(defaults.getServiceSigners(), override.getServiceSigners(), "service");
        serviceRegionSigners = mergeSignerMap(defaults.getServiceRegionSigners(),
                override.getServiceRegionSigners(), "service" + SERVICE_REGION_DELIMITOR + "region");
        httpClients = merge(defaults.getHttpClients(), override.getHttpClients());

        if (override.getUserAgentTemplate() != null) {
            userAgentTemplate = override.getUserAgentTemplate();
        } else {
            userAgentTemplate = defaults.getUserAgentTemplate();
        }
    }

    /**
     * Returns an immutable map by merging the override signer configuration
     * into the default signer configuration for the given theme.
     *
     * @param defaults
     *            default signer configuration
     * @param override
     *            signer configurations overrides
     * @param theme
     *            used for message logging. eg region, service, region+service
     */
    private Map<String, SignerConfig> mergeSignerMap(JsonIndex<SignerConfigJsonHelper, SignerConfig>[] defaults,
            JsonIndex<SignerConfigJsonHelper, SignerConfig>[] overrides, String theme) {
        Map<String, SignerConfig> map = buildSignerMap(defaults, theme);
        Map<String, SignerConfig> mapOverride = buildSignerMap(overrides, theme);
        map.putAll(mapOverride);
        return Collections.unmodifiableMap(map);
    }

    private <C extends Builder<T>, T> Map<String, T> merge(JsonIndex<C, T>[] defaults,
            JsonIndex<C, T>[] overrides) {
        Map<String, T> map = buildMap(defaults);
        Map<String, T> mapOverride = buildMap(overrides);
        map.putAll(mapOverride);
        return Collections.unmodifiableMap(map);
    }

    private <C extends Builder<T>, T> Map<String, T> buildMap(JsonIndex<C, T>[] signerIndexes) {
        Map<String, T> map = new HashMap<String, T>();
        if (signerIndexes != null) {
            for (JsonIndex<C, T> index : signerIndexes) {
                String region = index.getKey();
                T prev = map.put(region, index.newReadOnlyConfig());
                if (prev != null) {
                    log.warn("Duplicate definition of signer for " + index.getKey());
                }
            }
        }
        return map;
    }

    /**
     * Builds and returns a signer configuration map.
     *
     * @param signerIndexes
     *            signer configuration entries loaded from JSON
     * @param theme
     *            used for message logging. eg region, service, region+service
     */
    private Map<String, SignerConfig> buildSignerMap(
            JsonIndex<SignerConfigJsonHelper, SignerConfig>[] signerIndexes, String theme) {
        Map<String, SignerConfig> map = new HashMap<String, SignerConfig>();
        if (signerIndexes != null) {
            for (JsonIndex<SignerConfigJsonHelper, SignerConfig> index : signerIndexes) {
                String region = index.getKey();
                SignerConfig prev = map.put(region, index.newReadOnlyConfig());
                if (prev != null) {
                    log.warn("Duplicate definition of signer for " + theme + " " + index.getKey());
                }
            }
        }
        return map;
    }

    /**
     * Returns the signer configuration for the specified service, not
     * specific to any region.
     */
    public SignerConfig getSignerConfig(String serviceName) {
        return getSignerConfig(serviceName, null);
    }

    /**
     * Returns the http client configuration for the http client name.
     */
    public HttpClientConfig getHttpClientConfig(String httpClientName) {
        return httpClients.get(httpClientName);
    }

    /**
     * Returns the signer configuration for the specified service name and
     * an optional region name.
     * @param serviceName must not be null
     * @param regionName similar to the region name in {@link Regions};
     * can be null.
     * @return the signer
     */
    public SignerConfig getSignerConfig(String serviceName, String regionName) {
        if (serviceName == null)
            throw new IllegalArgumentException();
        SignerConfig signerConfig = null;
        if (regionName != null) {
            // Service+Region signer config has the highest precedence
            String key = serviceName + SERVICE_REGION_DELIMITOR + regionName;
            signerConfig = serviceRegionSigners.get(key);
            if (signerConfig != null) {
                return signerConfig;
            }
            // Region signer config has the 2nd highest precedence
            signerConfig = regionSigners.get(regionName);
            if (signerConfig != null) {
                return signerConfig;
            }
        }
        // Service signer config has the 3rd highest precedence
        signerConfig = serviceSigners.get(serviceName);
        // Fall back to the default
        return signerConfig == null ? defaultSignerConfig : signerConfig;
    }

    /**
     * @return the custom user agent template, if configured
     */
    public String getUserAgentTemplate() {
        return userAgentTemplate;
    }

    static InternalConfigJsonHelper loadfrom(URL url) throws JsonParseException, JsonMappingException, IOException {
        if (url == null)
            throw new IllegalArgumentException();
        InternalConfigJsonHelper target = Jackson.getObjectMapper().readValue(url, InternalConfigJsonHelper.class);
        return target;
    }

    /**
     * Loads and returns the AWS Java SDK internal configuration from the
     * classpath.
     */
    static InternalConfig load() throws JsonParseException, JsonMappingException, IOException {
        URL url = ClassLoaderHelper.getResource("/" + DEFAULT_CONFIG_RESOURCE, InternalConfig.class);
        if (url == null) { // Try without a leading "/"
            url = ClassLoaderHelper.getResource(DEFAULT_CONFIG_RESOURCE, InternalConfig.class);
        }
        InternalConfigJsonHelper config = loadfrom(url);
        InternalConfigJsonHelper configOverride;
        URL overrideUrl = ClassLoaderHelper.getResource("/" + CONFIG_OVERRIDE_RESOURCE, InternalConfig.class);
        if (overrideUrl == null) { // Try without a leading "/"
            overrideUrl = ClassLoaderHelper.getResource(CONFIG_OVERRIDE_RESOURCE, InternalConfig.class);
        }
        if (overrideUrl == null) {
            log.debug("Configuration override " + CONFIG_OVERRIDE_RESOURCE + " not found.");
            configOverride = new InternalConfigJsonHelper();
        } else {
            configOverride = loadfrom(overrideUrl);
        }
        return new InternalConfig(config, configOverride);
    }

    // For debugging purposes
    void dump() {
        StringBuilder sb = new StringBuilder().append("defaultSignerConfig: ").append(defaultSignerConfig)
                .append("\n").append("serviceRegionSigners: ").append(serviceRegionSigners).append("\n")
                .append("regionSigners: ").append(regionSigners).append("\n").append("serviceSigners: ")
                .append(serviceSigners).append("\n").append("userAgentTemplate: ").append(userAgentTemplate);
        log.debug(sb.toString());
    }

    public static class Factory {
        private static final InternalConfig SINGELTON;
        static {
            InternalConfig config = null;
            try {
                config = InternalConfig.load();
            } catch (RuntimeException ex) {
                throw ex;
            } catch (Exception ex) {
                throw new IllegalStateException("Fatal: Failed to load the internal config for AWS Java SDK", ex);
            }
            SINGELTON = config;
        }

        /**
         * Returns a non-null and immutable instance of the AWS SDK internal
         * configuration.
         */
        public static InternalConfig getInternalConfig() {
            return SINGELTON;
        }
    }
}