com.emc.storageos.driver.dellsc.scapi.rest.RestClient.java Source code

Java tutorial

Introduction

Here is the source code for com.emc.storageos.driver.dellsc.scapi.rest.RestClient.java

Source

/*
 * Copyright 2016 Dell Inc.
 *
 * 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 com.emc.storageos.driver.dellsc.scapi.rest;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;

import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.AuthCache;
import org.apache.http.client.CredentialsProvider;
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.HttpRequestBase;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.BasicAuthCache;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A basic REST client for SC API communication.
 */
public class RestClient implements AutoCloseable {

    private static final Logger LOG = LoggerFactory.getLogger(RestClient.class);
    private String baseUrl;
    private CloseableHttpClient httpClient;
    private HttpClientContext httpContext = null;

    /**
     * Instantiates a new Rest client.
     *
     * @param host Host name or IP address of the Dell Storage Manager server.
     * @param port Port the DSM data collector is listening on.
     * @param user The DSM user name to use.
     * @param password The DSM password.
     */
    public RestClient(String host, int port, String user, String password) {
        this.baseUrl = String.format("https://%s:%d/api/rest", host, port);

        try {
            // Set up auth handling
            CredentialsProvider credsProvider = new BasicCredentialsProvider();
            credsProvider.setCredentials(new AuthScope(host, port),
                    new UsernamePasswordCredentials(user, password));
            AuthCache authCache = new BasicAuthCache();
            BasicScheme basicAuth = new BasicScheme();
            HttpHost target = new HttpHost(host, port, "https");
            authCache.put(target, basicAuth);

            // Set up our context
            httpContext = HttpClientContext.create();
            httpContext.setCookieStore(new BasicCookieStore());
            httpContext.setAuthCache(authCache);

            // Create our HTTPS client
            SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, new TrustStrategy() {
                @Override
                public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
                    return true;
                }
            }).build();

            SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext,
                    SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

            this.httpClient = HttpClients.custom().setHostnameVerifier(new AllowAllHostnameVerifier())
                    .setDefaultCredentialsProvider(credsProvider).setSSLSocketFactory(sslSocketFactory).build();
        } catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException e) {
            // Hopefully default SSL handling is set up
            LOG.warn("Failed to configure HTTP handling, falling back to default handler.");
            LOG.debug("Config error: {}", e);
            this.httpClient = HttpClients.createDefault();
        }
    }

    @Override
    public void close() {
        try {
            httpClient.close();
        } catch (IOException e) {
        }
        httpContext = null;
    }

    /**
     * Format the REST endpoint URL.
     *
     * @param path The target path.
     * @return The full endpoint URL.
     */
    private String formatUrl(String path) {
        // Make sure URL is formatted how we expect
        String urlPath = path;
        if (!path.startsWith("/")) {
            urlPath = String.format("/%s", path);
        }

        return String.format("%s%s", this.baseUrl, urlPath);
    }

    /**
     * Execute a REST call.
     *
     * @param request The REST request.
     * @return The results from the execution.
     */
    private RestResult executeRequest(HttpRequestBase request) {
        RestResult result = null;

        request.addHeader("Accept", "application/json");
        request.addHeader("x-dell-api-version", "2.0");
        request.addHeader("Content-Type", "application/json; charset=utf-8");

        CloseableHttpResponse response = null;
        try {
            response = httpClient.execute(request, httpContext);
            HttpEntity entity = response.getEntity();
            result = new RestResult(request.getURI().toString(), response.getStatusLine().getStatusCode(),
                    response.getStatusLine().getReasonPhrase(),
                    entity != null ? EntityUtils.toString(response.getEntity()) : "");
        } catch (IOException e) {
            result = new RestResult(500, "Internal Failure", "");
            LOG.warn(String.format("Error in API request: %s", e), e);
        } finally {
            try {
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
            }
        }

        return result;
    }

    /**
     * Execute a GET REST call.
     *
     * @param path The relative path.
     * @return The execution result.
     */
    public RestResult get(String path) {
        HttpGet httpGet = new HttpGet(formatUrl(path));
        return executeRequest(httpGet);
    }

    /**
     * Execute a DELETE REST call.
     *
     * @param path The relative path.
     * @return The execution result.
     */
    public RestResult delete(String path) {
        HttpDelete httpDelete = new HttpDelete(formatUrl(path));
        return executeRequest(httpDelete);
    }

    /**
     * Execute a POST REST call.
     *
     * @param path The relative path.
     * @param payload The POST payload.
     * @return The execution result.
     */
    public RestResult post(String path, String payload) {
        HttpPost httpPost = new HttpPost(formatUrl(path));
        StringEntity entity = new StringEntity(payload, StandardCharsets.UTF_8);
        httpPost.setEntity(entity);

        return executeRequest(httpPost);
    }

    /**
     * Execute a PUT REST call.
     *
     * @param path The relative path.
     * @param payload The PUT payload.
     * @return The execution result.
     */
    public RestResult put(String path, String payload) {
        HttpPut httpPut = new HttpPut(formatUrl(path));
        httpPut.setEntity(new StringEntity(payload, StandardCharsets.UTF_8));
        return executeRequest(httpPut);
    }
}