com.jaspersoft.jasperserver.api.engine.jasperreports.util.AwsEc2MetadataClient.java Source code

Java tutorial

Introduction

Here is the source code for com.jaspersoft.jasperserver.api.engine.jasperreports.util.AwsEc2MetadataClient.java

Source

/*
 * Copyright (C) 2005 - 2014 TIBCO Software Inc. All rights reserved.
 * http://www.jaspersoft.com.
 *
 * Unless you have purchased  a commercial license agreement from Jaspersoft,
 * the following license terms  apply:
 *
 * This program is free software: you can redistribute it and/or  modify
 * it under the terms of the GNU Affero General Public License  as
 * published by the Free Software Foundation, either version 3 of  the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero  General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public  License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

package com.jaspersoft.jasperserver.api.engine.jasperreports.util;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static org.apache.commons.lang.StringUtils.isEmpty;
import static org.apache.commons.lang.StringUtils.isNotEmpty;

/**
 * JRS Client for accessing the Amazon EC2 Instance Metadata Service.
 *
 * @author vsabadosh
 */
public class AwsEc2MetadataClient {

    /** System property for overriding the Amazon EC2 Instance Metadata Service endpoint. */
    public static final String EC2_METADATA_SERVICE_OVERRIDE = "com.amazonaws.sdk.ec2MetadataServiceEndpointOverride";

    /** Default endpoint for the Amazon EC2 Instance Metadata Service. */
    private static final String EC2_METADATA_SERVICE_URL = "http://169.254.169.254";

    /** Default resource paths for Metadata items in the Amazon EC2 Instance Metadata Service. */
    public static final String INSTANCE_ID_RESOURCE = "/latest/meta-data/instance-id/";
    public static final String REGION_RESOURCE = "/latest/meta-data/placement/availability-zone/";
    public static final String MACS_RESOURCE = "/latest/meta-data/network/interfaces/macs/";
    public static final String PRIVATE_IP_RESOURCE = "/latest/meta-data/local-ipv4/";
    public static final String PUBLIC_IP_RESOURCE = "/latest/meta-data/public-ipv4/";
    public static final String PRODUCT_CODES_RESOURCE = "/latest/meta-data/product-codes";
    public static final String INSTANCE_TYPE_RESOURCE = "/latest/meta-data/instance-type";
    public static final String SECURITY_CREDENTIALS_RESOURCE = "/latest/meta-data/iam/security-credentials/";
    public static final String DOCUMENT_RESOURCE = "/latest/dynamic/instance-identity/document";
    public static final String ACCOUNT_ID = "accountId";
    public static final String AWS_DOMAIN = ".amazonaws.com";

    public static int SECOND = 1000;

    public static final String VPC_ID = "vpc-id";

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

    private static Map<String, String> metadataValuesCache = new HashMap<String, String>();

    private List<String> awsRegions;

    public AwsEc2MetadataClient() {

    }

    public void setAwsRegions(List<String> awsRegions) {
        this.awsRegions = awsRegions;
    }

    /**
     *
     * @param resource the resource path for target EC2 Instance Metadata item(ec. instance-id, instance-type, etc).
     * @return value of  EC2 Instance Metadata item
     */
    public String getEc2InstanceMetadataItem(String resource) {
        if (!metadataValuesCache.containsKey(resource)) {
            String value = readResource(resource);
            metadataValuesCache.put(resource, value);
            return value;
        } else {
            return metadataValuesCache.get(resource);
        }
    }

    public Boolean hasAwsProductCode(String jsProductCode) {
        if (!isNotEmpty(jsProductCode)) {
            return false;
        }
        List<String> ec2InstanceProductCodes = parseValueAsList(getEc2InstanceMetadataItem(PRODUCT_CODES_RESOURCE));
        if (ec2InstanceProductCodes != null && ec2InstanceProductCodes.size() > 0) {
            for (String productCode : ec2InstanceProductCodes) {
                if (productCode.equals(jsProductCode)) {
                    return true;
                }
            }
        }
        return false;
    }

    public Boolean hasAwsAccountId(String jsAmazonAccountId) {
        if (!isNotEmpty(jsAmazonAccountId)) {
            return false;
        }
        String accountId = parsePropertyValueFromJson(getEc2InstanceMetadataItem(DOCUMENT_RESOURCE), ACCOUNT_ID);
        return (accountId != null && accountId.equals(jsAmazonAccountId));
    }

    public Boolean hasSecurityCredentials() {
        String securityCredentialsList = getEc2InstanceMetadataItem(SECURITY_CREDENTIALS_RESOURCE);
        return securityCredentialsList != null && securityCredentialsList.trim().length() > 0;
    }

    public Boolean isEc2InstanceInTargetVpc(String vpcId) {
        if (!isNotEmpty(vpcId) && !isEc2InstanceInVpc()) {
            return true;
        }
        if (isNotEmpty(vpcId)) {
            List<String> ec2MacAddresses = parseValueAsList(getEc2InstanceMetadataItem(MACS_RESOURCE));
            if (ec2MacAddresses != null) {
                for (String ec2MacAddress : ec2MacAddresses) {
                    String ec2VpcId = getEc2InstanceMetadataItem(MACS_RESOURCE + ec2MacAddress + VPC_ID);
                    if (ec2VpcId != null && ec2VpcId.trim().equals(vpcId.trim())) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    public Boolean isEc2InstanceInVpc() {
        List<String> ec2MacAddresses = parseValueAsList(getEc2InstanceMetadataItem(MACS_RESOURCE));
        if (ec2MacAddresses != null && ec2MacAddresses.size() > 0) {
            for (String ec2MacAddress : ec2MacAddresses) {
                List<String> networkInformation = parseValueAsList(
                        getEc2InstanceMetadataItem(MACS_RESOURCE + ec2MacAddress));
                if (networkInformation != null && networkInformation.size() > 0) {
                    if (networkInformation.contains(VPC_ID)) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    public boolean isEc2Instance() {
        return getAwsAccountId() != null;
    }

    public String getEc2InstanceId() {
        return getEc2InstanceMetadataItem(AwsEc2MetadataClient.INSTANCE_ID_RESOURCE);
    }

    public String getAwsAccountId() {
        return parsePropertyValueFromJson(getEc2InstanceMetadataItem(DOCUMENT_RESOURCE), ACCOUNT_ID);
    }

    public String getEc2InstanceRegion() {
        return parseRegionFromSubRegion(getEc2InstanceMetadataItem(AwsEc2MetadataClient.REGION_RESOURCE));
    }

    public String getEc2InstanceFullRegion() {
        return getEc2InstanceMetadataItem(AwsEc2MetadataClient.REGION_RESOURCE) + AWS_DOMAIN;
    }

    private String parseRegionFromSubRegion(String region) {
        if (region != null) {
            for (String awsRegion : awsRegions) {
                String[] parse = awsRegion.split(AWS_DOMAIN);
                if (region.contains(parse[0])) {
                    return awsRegion;
                }
            }
        }
        return null;
    }

    private List<String> parseValueAsList(String value) {
        if (value != null && value.trim().length() > 0) {
            String[] values = value.trim().split("\n");
            List<String> valueList = new ArrayList<String>();
            for (String val : values) {
                valueList.add(val.trim());
            }
            return valueList;
        }
        return null;
    }

    public String parsePropertyValueFromJson(String jsonText, String property) {
        if (isEmpty(jsonText) || isEmpty(property)) {
            return null;
        }

        Matcher matcher = Pattern.compile("(\"" + property + "\")\\s*:\\s*\"([^\"]+)").matcher(jsonText);
        if (matcher.find()) {
            return matcher.group(2);
        } else {
            return null;
        }
    }

    private URL getEc2MetadataServiceUrlForResource(String resourcePath) throws Exception {
        String endpoint = EC2_METADATA_SERVICE_URL;
        if (System.getProperty(EC2_METADATA_SERVICE_OVERRIDE) != null) {
            endpoint = System.getProperty(EC2_METADATA_SERVICE_OVERRIDE);
        }

        return new URL(endpoint + resourcePath);
    }

    private String readResource(String resourcePath) {
        HttpURLConnection connection = null;
        URL url = null;
        try {
            url = getEc2MetadataServiceUrlForResource(resourcePath);
            log.debug("Connecting to EC2 instance metadata service at URL: " + url.toString());
            connection = (HttpURLConnection) url.openConnection();
            connection.setConnectTimeout(SECOND * 2);
            connection.setReadTimeout(SECOND * 7);
            connection.setRequestMethod("GET");
            connection.setDoOutput(true);
            connection.connect();

            if (connection.getResponseCode() >= HttpURLConnection.HTTP_OK
                    && connection.getResponseCode() < HttpURLConnection.HTTP_BAD_REQUEST) {
                return readResponse(connection);
            } else {
                return null;
            }
        } catch (Exception e) {
            return null;
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
    }

    private String readResponse(HttpURLConnection connection) throws IOException {
        InputStream inputStream = connection.getInputStream();

        try {
            StringBuilder buffer = new StringBuilder();
            while (true) {
                int c = inputStream.read();
                if (c == -1)
                    break;
                buffer.append((char) c);
            }

            return buffer.toString();
        } finally {
            inputStream.close();
        }
    }

}