org.mycontroller.restclient.core.RestHttpClient.java Source code

Java tutorial

Introduction

Here is the source code for org.mycontroller.restclient.core.RestHttpClient.java

Source

/*
 * Copyright 2015-2018 Jeeva Kandasamy (jkandasa@gmail.com)
 * and other contributors as indicated by the @author tags.
 *
 * 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://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License 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 org.mycontroller.restclient.core;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.mycontroller.restclient.core.typeresolvers.CollectionJavaTypeResolver;
import org.mycontroller.restclient.core.typeresolvers.MapJavaTypeResolver;
import org.mycontroller.restclient.core.typeresolvers.SimpleJavaTypeResolver;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;

import lombok.extern.slf4j.Slf4j;

/**
 * @author Jeeva Kandasamy (jkandasa)
 * @since 2.1.0
 */

@Slf4j
public class RestHttpClient {

    // https://httpstatuses.com/
    public enum STATUS_CODE {
        OK(200), CREATED(201), ACCEPTED(202), NO_CONTENT(204), BAD_REQUEST(400), UNAUTHORIZED(401), FORBIDDEN(
                403), NOT_FOUND(404);

        int code;

        STATUS_CODE(int code) {
            this.code = code;
        }

        public int getCode() {
            return code;
        }
    }

    private CloseableHttpClient client = null;
    private RequestConfig customRequestConfig = null;

    private ObjectMapper mapper = new RestObjectMapper();

    private SimpleJavaTypeResolver simpleJavaTypeResolver = new SimpleJavaTypeResolver();
    private CollectionJavaTypeResolver collectionJavaTypeResolver = new CollectionJavaTypeResolver();
    private MapJavaTypeResolver mapJavaTypeResolver = new MapJavaTypeResolver();

    public RestHttpClient() {
        client = HttpClientBuilder.create().build();
    }

    public RestHttpClient(TRUST_HOST_TYPE trustHostType) {
        customRequestConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD).build();
        if (trustHostType == TRUST_HOST_TYPE.ANY) {
            client = getHttpClientTrustAll();
        } else {
            client = getHttpClient();
        }
    }

    protected CloseableHttpClient getHttpClient() {
        return HttpClients.custom().setDefaultRequestConfig(customRequestConfig).build();
    }

    //trust any host
    private CloseableHttpClient getHttpClientTrustAll() {
        SSLContextBuilder builder = new SSLContextBuilder();
        try {
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            builder.loadTrustMaterial(keyStore, new TrustStrategy() {
                @Override
                public boolean isTrusted(X509Certificate[] trustedCert, String nameConstraints)
                        throws CertificateException {
                    return true;
                }
            });
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build(),
                    new AnyHostnameVerifier());
            return HttpClients.custom().setSSLSocketFactory(sslsf).setDefaultRequestConfig(customRequestConfig)
                    .build();
        } catch (Exception ex) {
            _logger.error("Exception, ", ex);
            throw new RuntimeException("Unable to create trust ANY http client. Error: " + ex.getMessage());
        }
    }

    //Trust all hostname
    class AnyHostnameVerifier implements HostnameVerifier {
        @Override
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }

    }

    private RestHttpResponse execute(HttpUriRequest request) {
        CloseableHttpResponse response = null;
        try {
            response = client.execute(request);
            return RestHttpResponse.get(request.getURI(), response);
        } catch (Exception ex) {
            _logger.debug("Exception,", ex);
            throw new RuntimeException(
                    MessageFormat.format("Failed to execute, Request:{0}, error:{1}", request, ex.getMessage()));
        } finally {
            if (response != null) {
                try {
                    response.close();
                } catch (IOException ex) {
                    _logger.error("Exception,", ex);
                }
            }
        }
    }

    private URI getURI(String url, Map<String, Object> queryParameters) throws URISyntaxException {
        if (queryParameters != null && !queryParameters.isEmpty()) {
            List<NameValuePair> queryParams = new ArrayList<NameValuePair>();
            for (String key : queryParameters.keySet()) {
                queryParams.add(new BasicNameValuePair(key, String.valueOf(queryParameters.get(key))));
            }
            return new URIBuilder(url).addParameters(queryParams).build();
        } else {
            return new URIBuilder(url).build();
        }
    }

    // GET, POST, PUT, DELETE methods start

    // HTTP DELETE request
    protected RestHttpResponse doDelete(String url, Integer expectedResponseCode) {
        return doDelete(url, RestHeader.getDefault(), expectedResponseCode);
    }

    // HTTP DELETE request - primary method
    protected RestHttpResponse doDelete(String url, RestHeader header, Integer expectedResponseCode) {
        HttpDelete delete = new HttpDelete(url);
        header.updateHeaders(delete);
        RestHttpResponse httpResponse = execute(delete);
        // validate response
        validateResponse(httpResponse, expectedResponseCode);
        return httpResponse;
    }

    // HTTP GET request
    protected RestHttpResponse doGet(String url, Integer expectedResponseCode) {
        return doGet(url, null, RestHeader.getDefault(), expectedResponseCode);
    }

    // HTTP GET request
    protected RestHttpResponse doGet(String url, Map<String, Object> queryParameters,
            Integer expectedResponseCode) {
        return doGet(url, queryParameters, RestHeader.getDefault(), expectedResponseCode);
    }

    // HTTP GET request - primary method
    protected RestHttpResponse doGet(String url, Map<String, Object> queryParameters, RestHeader header,
            Integer expectedResponseCode) {
        try {
            HttpGet get = new HttpGet(getURI(url, queryParameters));
            header.updateHeaders(get);
            // execute
            RestHttpResponse httpResponse = execute(get);
            // validate response
            validateResponse(httpResponse, expectedResponseCode);
            return httpResponse;
        } catch (Exception ex) {
            _logger.error("Exception when calling url:[{}], headers:[{}]", url, header, ex);
            throw new RuntimeException(
                    MessageFormat.format("Failed to execute, url:{0}, error:{1}", url, ex.getMessage()));
        }
    }

    // HTTP GET request
    protected RestHttpResponse doGet(String url, RestHeader header, Integer expectedResponseCode) {
        return doGet(url, null, header, expectedResponseCode);
    }

    // HTTP POST request - primary method
    protected RestHttpResponse doPost(String url, Map<String, Object> queryParameters, RestHeader header,
            HttpEntity entity, Integer expectedResponseCode) {
        try {
            HttpPost post = new HttpPost(getURI(url, queryParameters));
            header.updateHeaders(post);
            post.setEntity(entity);
            // execute
            RestHttpResponse httpResponse = execute(post);
            // validate response
            validateResponse(httpResponse, expectedResponseCode);
            return httpResponse;
        } catch (Exception ex) {
            _logger.error("Exception when calling url:[{}], headers:[{}], queryParameters:[{}]", url, header,
                    queryParameters, ex);
            throw new RuntimeException(
                    MessageFormat.format("Failed to execute, url:{0}, error:{1}", url, ex.getMessage()));
        }
    }

    // HTTP POST request
    protected RestHttpResponse doPost(String url, Map<String, Object> queryParameters, RestHeader header,
            Integer expectedResponseCode) {
        StringEntity stringEntity = null;
        return doPost(url, queryParameters, header, stringEntity, expectedResponseCode);
    }

    // HTTP POST request
    protected RestHttpResponse doPost(String url, Map<String, Object> queryParameters, RestHeader header,
            String entity, Integer expectedResponseCode) {
        _logger.debug("Entity: {}", entity);
        try {
            return doPost(url, queryParameters, header, new StringEntity(entity), expectedResponseCode);
        } catch (UnsupportedEncodingException ex) {
            _logger.error("Exception when calling url:[{}], queryParameters:[{}], headers:[{}], entity:[{}]", url,
                    queryParameters, header, entity, ex);
            throw new RuntimeException(
                    MessageFormat.format("Failed to execute, url:{0}, error:{1}", url, ex.getMessage()));
        }
    }

    // HTTP POST request
    protected RestHttpResponse doPost(String url, RestHeader header, String entity, Integer expectedResponseCode) {
        return doPost(url, null, header, entity, expectedResponseCode);
    }

    // HTTP PUT request
    protected RestHttpResponse doPut(String url, RestHeader header, HttpEntity entity,
            Integer expectedResponseCode) {
        HttpPut put = new HttpPut(url);
        header.updateHeaders(put);
        put.setEntity(entity);
        // execute
        RestHttpResponse httpResponse = execute(put);
        // validate response
        validateResponse(httpResponse, expectedResponseCode);
        return httpResponse;
    }

    // HTTP PUT request
    protected RestHttpResponse doPut(String url, RestHeader header, Integer expectedResponseCode) {
        StringEntity stringEntity = null;
        return doPut(url, header, stringEntity, expectedResponseCode);
    }

    // HTTP PUT request
    protected RestHttpResponse doPut(String url, RestHeader header, String entity, Integer expectedResponseCode) {
        _logger.debug("Entity: {}", entity);
        try {
            return doPut(url, header, new StringEntity(entity), expectedResponseCode);
        } catch (UnsupportedEncodingException ex) {
            _logger.error("Exception when calling url:[{}], headers:[{}], entity:[{}]", url, header, entity, ex);
            throw new RuntimeException(
                    MessageFormat.format("Failed to execute, url:{0}, error:{1}", url, ex.getMessage()));
        }
    }

    public String getHeader(RestHttpResponse response, String name) {
        Header[] headers = response.getHeaders();
        for (int index = 0; index < headers.length; index++) {
            Header header = headers[index];
            if (header.getName().equalsIgnoreCase(name)) {
                return header.getValue();
            }
        }
        return null;
    }

    public void updateOnNull(Map<String, Object> data, String key, Object value) {
        if (data.get(key) == null) {
            data.put(key, value);
        }
    }

    // validate response
    public void validateResponse(RestHttpResponse response, Integer expectedResponseCode) {
        _logger.debug("{}", response);
        if (expectedResponseCode != null) {
            if (!response.getResponseCode().equals(expectedResponseCode)) {
                throw new RuntimeException("Did not match with expected response code[" + expectedResponseCode
                        + "], " + response.toString());
            }
        }
    }

    public SimpleJavaTypeResolver simpleResolver() {
        return simpleJavaTypeResolver;
    }

    public CollectionJavaTypeResolver collectionResolver() {
        return collectionJavaTypeResolver;
    }

    public MapJavaTypeResolver mapResolver() {
        return mapJavaTypeResolver;
    }

    public Object readValue(String entity, JavaType javaType) {
        try {
            return mapper.readValue(entity, javaType);
        } catch (IOException ex) {
            _logger.error("Exception: entity[{}]", entity, ex);
            throw new RuntimeException("Exception: " + ex.getMessage());
        }
    }

    public String toJsonString(Object object) {
        try {
            return mapper.writeValueAsString(object);
        } catch (JsonProcessingException ex) {
            _logger.error("Exception,", ex);
            throw new RuntimeException("Exception: " + ex.getMessage());
        }
    }

}