org.apache.ambari.funtest.server.AmbariHttpWebRequest.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.ambari.funtest.server.AmbariHttpWebRequest.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.apache.ambari.funtest.server;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.stream.JsonReader;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethodBase;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.DeleteMethod;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.PutMethod;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.commons.codec.binary.Base64;

import java.io.IOException;
import java.io.StringReader;
import java.util.Map;

/**
 * REST API Client that performs various operations on the Ambari Server
 * using Http.
 */
public class AmbariHttpWebRequest extends WebRequest {
    private static final Log LOG = LogFactory.getLog(AmbariHttpWebRequest.class);
    private static String SERVER_URL_FORMAT = "http://%s:%d";
    private static String SERVER_SSL_URL_FORMAT = "https://%s:%d";

    private String content;

    private String serverName;
    private int serverApiPort;
    private int serverAgentPort;
    private WebResponse response;
    private String curlApi;

    /**
     *  Constructor to set the REST API URL, Server API port, Server Agent API port, user id and password.
     *
     * @param params
     */
    public AmbariHttpWebRequest(ConnectionParams params) {
        setServerName(params.getServerName());
        setServerApiPort(params.getServerApiPort());
        setServerAgentPort(params.getServerAgentPort());
        setUserName(params.getUserName());
        setPassword(params.getPassword());
        addHeader("X-Requested-By", "ambari");
        if (getUserName() != null) {
            addHeader("Authorization", getBasicAuthentication());
        }
    }

    /**
     * Sends the request to the Ambari server and returns the response.
     *
     * @return - Response from the Ambari server.
     * @throws IOException
     */
    @Override
    public WebResponse getResponse() throws IOException {
        if (response == null) {
            LOG.info(getCurlApi());
            response = executeRequest();
        }

        return response;
    }

    /**
     * Gets the full URI
     *
     * @return - Full path to the URI
     */
    @Override
    public String getUrl() {
        return getServerApiUrl() + getApiPath();
    }

    /**
     * Gets the JSON content (request data).
     *
     * @return - JSON content.
     */
    @Override
    public String getContent() {
        if (content == null) {
            content = getRequestData();
        }

        return content;
    }

    /**
     * Gets the content encoding.
     *
     * @return - Content encoding.
     */
    @Override
    public String getContentEncoding() {
        return "UTF-8";
    }

    /**
     * Gets the content type, like application/json, application/text, etc.
     *
     * @return - Content type.
     */
    @Override
    public String getContentType() {
        return "application/json";
    }

    /**
     * Gets the curl command line call for this request. Useful for
     * debugging.
     *
     * @return - Curl command line call.
     */
    public String getCurlApi() {
        if (curlApi == null) {
            StringBuilder sb = new StringBuilder();
            sb.append("curl");
            if (getUserName() != null) {
                sb.append(String.format(" -u %s", getUserName()));
                if (getPassword() != null) {
                    sb.append(String.format(":%s", getPassword()));
                }
            }
            sb.append(String.format(" -H \"%s\"", "X-Requested-By: ambari"));
            sb.append(String.format(" -X %s", getHttpMethod()));
            if (getHttpMethod().equals("PUT") || getHttpMethod().equals("POST")) {
                if (getContent() != null) {
                    sb.append(String.format(" -d '%s'", getContent()));
                }
            }
            sb.append(String.format(" %s", getUrl()));
            curlApi = sb.toString();
        }

        return curlApi;
    }

    /**
     * Sets the REST API URL for the Ambari Server
     *
     * @param serverName - REST API URL
     */
    public void setServerName(String serverName) {
        this.serverName = serverName;
    }

    /**
     * Gets the REST API URL for the Ambari Server
     *
     * @return - REST API URL
     */
    public String getServerName() {
        return this.serverName;
    }

    /**
     * Gets the port number for the REST API used by the web clients.
     *
     * @return - Server API port number.
     */
    public int getServerApiPort() {
        return this.serverApiPort;
    }

    /**
     * Sets the port number for the REST API used by the web clients.
     *
     * @param serverApiPort - Server API port.
     */
    public void setServerApiPort(int serverApiPort) {
        this.serverApiPort = serverApiPort;
    }

    /**
     * Gets the port number for the REST API used by the agent.
     *
     * @return - Agent API port number.
     */
    public int getServerAgentPort() {
        return this.serverAgentPort;
    }

    /**
     * Sets the port number for the REST API used by the agent.
     *
     * @param serverAgentPort - Agent API port number.
     */
    public void setServerAgentPort(int serverAgentPort) {
        this.serverAgentPort = serverAgentPort;
    }

    /**
     * Gets the REST API path fragment.
     *
     * @return - REST API path.
     */
    protected String getApiPath() {
        return "";
    }

    /**
     * Gets the request data used in POST and PUT requests.
     *
     * @return - Request data.
     */
    protected String getRequestData() {
        return "";
    }

    /**
     * Gets the basic authentication string to be used for the Authorization header.
     *
     * @return - Base-64 encoded authentication string.
     */
    protected String getBasicAuthentication() {
        String authString = getUserName() + ":" + getPassword();
        byte[] authEncBytes = Base64.encodeBase64(authString.getBytes());
        String authStringEnc = new String(authEncBytes);

        return "Basic " + authStringEnc;
    }

    /**
     * Gets URL for the Ambari Server (without the API path)
     *
     * @return - Ambari server URL.
     */
    protected String getServerApiUrl() {
        return String.format(SERVER_URL_FORMAT, getServerName(), getServerApiPort());
    }

    /**
     * Gets URL for the Agent Server (without the API path)
     *
     * @return - Agent server URL.
     */
    protected String getServerAgentUrl() {
        return String.format(SERVER_URL_FORMAT, getServerName(), getServerAgentPort());
    }

    /**
     * Helper method to create simple Json objects.
     *
     * @param name - Name
     * @param value - Value
     * @return - A JsonObject {name: value}
     */
    protected static JsonObject createJsonObject(String name, String value) {
        JsonObject jsonObject = new JsonObject();
        jsonObject.addProperty(name, value);
        return jsonObject;
    }

    /**
     * Helper method to create simple Json objects.
     *
     * @param name - Name
     * @param jsonElement - Json object.
     * @return - A JsonObject {name: jsonElement }
     */
    protected static JsonObject createJsonObject(String name, JsonElement jsonElement) {
        JsonObject jsonObject = new JsonObject();
        jsonObject.add(name, jsonElement);
        return jsonObject;
    }

    /**
     * Executes the current request by using HttpClient methods and returns the response.
     *
     * @return - Response from the Ambari server/Agent server.
     * @throws IOException
     */
    private WebResponse executeRequest() throws IOException {
        HttpMethodBase methodBase = null;
        String httpMethod;

        httpMethod = getHttpMethod();

        if (httpMethod.equals("GET")) {
            methodBase = getGetMethod();
        } else if (httpMethod.equals("POST")) {
            methodBase = getPostMethod();
        } else if (httpMethod.equals("PUT")) {
            methodBase = getPutMethod();
        } else if (httpMethod.equals("DELETE")) {
            methodBase = getDeleteMethod();
        } else {
            new RuntimeException(String.format("Unsupported HTTP method: %s", httpMethod));
        }

        WebResponse response = new WebResponse();
        HttpClient httpClient = new HttpClient();
        Map<String, String> headers = getHeaders();

        for (Map.Entry<String, String> header : headers.entrySet()) {
            methodBase.addRequestHeader(header.getKey(), header.getValue());
        }

        methodBase.setQueryString(getQueryString());

        try {
            int statusCode = httpClient.executeMethod(methodBase);
            response.setStatusCode(statusCode);
            response.setContent(methodBase.getResponseBodyAsString());
        } finally {
            methodBase.releaseConnection();
        }

        return response;
    }

    /**
     * Constructs a GetMethod instance.
     *
     * @return - GetMethod.
     */
    private GetMethod getGetMethod() {
        return new GetMethod(getUrl());
    }

    /**
     * Constructs a PutMethod instance and sets the request data on it.
     *
     * @return - PutMethod.
     */
    @SuppressWarnings("deprecation")
    private PutMethod getPutMethod() {
        PutMethod putMethod = new PutMethod(getUrl());

        putMethod.setRequestBody(getContent());

        return putMethod;
    }

    /**
     * Constructs a PostMethod and sets the request data on it.
     *
     * @return - PostMethod.
     */
    @SuppressWarnings("deprecation")
    private PostMethod getPostMethod() {
        PostMethod postMethod = new PostMethod(getUrl());

        /*
        RequestEntity requestEntity = new StringRequestEntity(
            request.getContent(),
            request.getContentType(),
            request.getContentEncoding());
            
        postMethod.setRequestEntity(requestEntity);
        */

        postMethod.setRequestBody(getContent());

        return postMethod;
    }

    /**
     * Constructs a DeleteMethod.
     *
     * @return - DeleteMethod.
     */
    private DeleteMethod getDeleteMethod() {
        return new DeleteMethod(getUrl());
    }

    @SuppressWarnings("deprecation")
    private RuntimeException createRuntimeException(HttpException httpException) {
        String message = httpException.getMessage();
        try {
            JsonElement jsonElement = new JsonParser()
                    .parse(new JsonReader(new StringReader(httpException.getMessage())));
            if (jsonElement != null && jsonElement.getAsJsonObject().has("message")) {
                message = jsonElement.getAsJsonObject().get("message").getAsString();
            }
        } catch (Throwable t) {
        }
        if (httpException.getReasonCode() != HttpStatus.SC_OK) {
            message = httpException.getReasonCode() + " " + httpException.getReason() + ": " + message;
        }
        return new RuntimeException(message, httpException);
    }
}