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

com.amazonaws.internal.EC2ResourceFetcher Maven / Gradle / Ivy

Go to download

The AWS SDK for Java - Core module holds the classes that are used by the individual service clients to interact with Amazon Web Services. Users need to depend on aws-java-sdk artifact for accessing individual client classes.

There is a newer version: 1.12.778
Show newest version
/*
 * Copyright 2011-2024 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.
 * You may obtain a copy of the License at:
 *
 *    http://aws.amazon.com/apache2.0
 *
 * 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;


import com.amazonaws.AmazonServiceException;
import com.amazonaws.SdkClientException;
import com.amazonaws.annotation.SdkInternalApi;
import com.amazonaws.annotation.SdkTestInternalApi;
import com.amazonaws.retry.internal.CredentialsEndpointRetryParameters;
import com.amazonaws.retry.internal.CredentialsEndpointRetryPolicy;
import com.amazonaws.util.IOUtils;
import com.amazonaws.util.VersionInfoUtils;
import com.amazonaws.util.json.Jackson;
import com.fasterxml.jackson.databind.JsonNode;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

@SdkInternalApi
public abstract class EC2ResourceFetcher {

    private static final Log LOG = LogFactory.getLog(EC2ResourceFetcher.class);

    private final ConnectionUtils connectionUtils;

    private static final String USER_AGENT = VersionInfoUtils.getUserAgent();

    EC2ResourceFetcher() {
        connectionUtils = ConnectionUtils.getInstance();
    }

    @SdkTestInternalApi
    EC2ResourceFetcher(ConnectionUtils connectionUtils) {
        this.connectionUtils = connectionUtils;
    }

    public static EC2ResourceFetcher defaultResourceFetcher() {
        return DefaultEC2ResourceFetcher.DEFAULT_BASE_RESOURCE_FETCHER;
    }

    public abstract String readResource(URI endpoint, CredentialsEndpointRetryPolicy retryPolicy, Map headers);

    public final String readResource(URI endpoint) {
        return readResource(endpoint, CredentialsEndpointRetryPolicy.NO_RETRY, null);
    }

    public final String readResource(URI endpoint, CredentialsEndpointRetryPolicy retryPolicy) {
        return readResource(endpoint, retryPolicy, null);
    }

    final String doReadResource(URI endpoint, CredentialsEndpointRetryPolicy retryPolicy, Map headers) {
        return doReadResource(endpoint, retryPolicy, headers, "GET");
    }

    final String doReadResource(URI endpoint, CredentialsEndpointRetryPolicy retryPolicy, Map headers, String method) {
        int retriesAttempted = 0;
        InputStream inputStream = null;
        Map headersToSent = addDefaultHeaders(headers);
        while (true) {
            InputStream toClose = null;
            try {
                long start = 0;
                if (LOG.isDebugEnabled()) {
                    LOG.debug("Executing " + method + " " + endpoint + " with headers " + headersToSent.keySet());
                    start = System.currentTimeMillis();
                }
                HttpURLConnection connection = connectionUtils.connectToEndpoint(endpoint, headersToSent, method);

                int statusCode = connection.getResponseCode();
                if (LOG.isDebugEnabled()) {
                    LOG.debug("Got response code " + statusCode + " from " + method + " " + endpoint);
                }

                if (statusCode >= 400) {
                    toClose = connection.getErrorStream();
                } else {
                    toClose = connection.getInputStream();
                }

                if (statusCode == HttpURLConnection.HTTP_OK) {
                    inputStream = connection.getInputStream();
                    String result = IOUtils.toString(inputStream);
                    if (LOG.isDebugEnabled()) {
                        long duration = System.currentTimeMillis() - start;
                        LOG.debug("Completed " + method + " " + endpoint + " after " + duration + "ms");
                    }
                    return result;
                } else if (statusCode == HttpURLConnection.HTTP_NOT_FOUND) {
                    // This is to preserve existing behavior of EC2 Instance metadata service.
                    throw new SdkClientException("The requested metadata is not found at " + connection.getURL());
                } else {
                    if (!retryPolicy.shouldRetry(retriesAttempted++,
                                                 CredentialsEndpointRetryParameters.builder().withStatusCode(statusCode).build())) {
                        inputStream = connection.getErrorStream();
                        handleErrorResponse(inputStream, statusCode, connection.getResponseMessage());
                    }
                }
            } catch (IOException ioException) {
                if (!retryPolicy.shouldRetry(retriesAttempted++,
                                             CredentialsEndpointRetryParameters.builder().withException(ioException).build())) {
                    throw new SdkClientException("Failed to connect to service endpoint: ", ioException);
                }
                LOG.debug("An IOException occurred when connecting to service endpoint: " + endpoint + "\n Retrying to connect "
                          + "again.");
            } finally {
                IOUtils.closeQuietly(toClose, LOG);
            }
        }
    }


    protected final Map addDefaultHeaders(Map headers) {
        HashMap map = new HashMap();
        if (headers != null) {
            map.putAll(headers);
        }

        putIfAbsent(map, "User-Agent", USER_AGENT);
        putIfAbsent(map, "Accept", "*/*");
        putIfAbsent(map, "Connection", "keep-alive");
        return map;
    }

    private  void putIfAbsent(Map map, K key, V value) {
        if (map.get(key) == null) {
            map.put(key, value);
        }
    }

    private void handleErrorResponse(InputStream errorStream, int statusCode, String responseMessage) throws IOException {
        String errorCode = null;

        // Parse the error stream returned from the service.
        if (errorStream != null) {
            String errorResponse = IOUtils.toString(errorStream);

            try {
                JsonNode node = Jackson.jsonNodeOf(errorResponse);
                JsonNode code = node.get("code");
                JsonNode message = node.get("message");
                if (code != null && message != null) {
                    errorCode = code.asText();
                    responseMessage = message.asText();
                }
            } catch (Exception exception) {
                LOG.debug("Unable to parse error stream");
            }
        }

        AmazonServiceException ase = new AmazonServiceException(responseMessage);
        ase.setStatusCode(statusCode);
        ase.setErrorCode(errorCode);
        throw ase;
    }

    static final class DefaultEC2ResourceFetcher extends EC2ResourceFetcher {
        private static final DefaultEC2ResourceFetcher DEFAULT_BASE_RESOURCE_FETCHER = new DefaultEC2ResourceFetcher();

        DefaultEC2ResourceFetcher() {
        }

        @SdkTestInternalApi
        DefaultEC2ResourceFetcher(ConnectionUtils connectionUtils) {
            super(connectionUtils);
        }

        @Override
        public String readResource(URI endpoint, CredentialsEndpointRetryPolicy retryPolicy, Map headers) {
            return doReadResource(endpoint, retryPolicy, headers);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy