com.ooyala.api.OoyalaApiClient.java Source code

Java tutorial

Introduction

Here is the source code for com.ooyala.api.OoyalaApiClient.java

Source

/**
 *
 * adapted from https://github.com/ooyala/java-v2-sdk
 *
 *
 * Copyright 2011  Ooyala, Inc.  All rights reserved.
 * <p/>
 * Ooyala, Inc. (Ooyala?) hereby grants permission, free of charge, to any person or entity obtaining a copy of the software code provided in source code format via this webpage and direct links contained within this webpage and any associated documentation (collectively, the "Software"), to use, copy, modify, merge, and/or publish the Software and, subject to pass-through of all terms and conditions hereof, permission to transfer, distribute and sublicense the Software; all of the foregoing subject to the following terms and conditions:
 * <p/>
 * 1.  The above copyright notice and this permission notice shall be included in all copies or portions of the Software.
 * <p/>
 * 2.   For purposes of clarity, the Software does not include any APIs, but instead consists of code that may be used in conjunction with APIs that may be provided by Ooyala pursuant to a separate written agreement subject to fees.
 * <p/>
 * 3.   Ooyala may in its sole discretion maintain and/or update the Software.  However, the Software is provided without any promise or obligation of support, maintenance or update.
 * <p/>
 * 4.  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, RELATING TO, ARISING FROM, IN CONNECTION WITH, OR INCIDENTAL TO THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 * <p/>
 * 5.   TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, (i) IN NO EVENT SHALL OOYALA BE LIABLE FOR ANY CONSEQUENTIAL, INCIDENTAL, INDIRECT, SPECIAL, PUNITIVE, OR OTHER DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS) RELATING TO, ARISING FROM, IN CONNECTION WITH, OR INCIDENTAL TO THE SOFTWARE OR THE USE OF OR INABILITY TO USE THE SOFTWARE, EVEN IF OOYALA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, AND (ii) OOYALAS TOTAL AGGREGATE LIABILITY RELATING TO, ARISING FROM, IN CONNECTION WITH, OR INCIDENTAL TO THE SOFTWARE SHALL BE LIMITED TO THE ACTUAL DIRECT DAMAGES INCURRED UP TO MAXIMUM AMOUNT OF FIFTY DOLLARS ($50).
 */

package com.ooyala.api;

import net.sf.json.JSON;
import net.sf.json.JSONSerializer;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
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.entity.AbstractHttpEntity;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * adapted from https://github.com/ooyala/java-v2-sdk
 *
 * The OoyalaApiClient class implements methods to call the V2 Ooyala API.
 * <p>
 * It uses the Simple.JSON Java library to parse JSON (see: http://code.google.com/p/json-simple/)
 * <p>
 * Please keep in mind that when creating your HashMap to send the JSON body, align to using Maps and Lists as the Simple.JSON library indicates.
 */
public class OoyalaApiClient {

    private HttpClient httpClient;

    private HttpClient getHttpClient() {
        return httpClient;
    }

    private void setHttpClient(HttpClient httpClient) {
        this.httpClient = httpClient;
    }

    /**
     * the Secret key
     */
    private String secretKey;

    /**
     * The API key
     */
    private String apiKey;

    /**
     * Base URL to Ooyala API
     */
    private String baseURL;

    /**
     * Represents the HTTP Status Code from the last response
     */
    private int responseCode;

    /**
     * The request's content type
     */
    private String contentType;

    private SignatureGenerator signatureGenerator;

    /**
     * Constructor with keys
     *
     * @param apiKey    The API keyyeah
     * @throws OoyalaApiException
     */
    public OoyalaApiClient(HttpClient client, String apiKey, String secretKey) throws OoyalaApiException {
        try {
            this.httpClient = client;
            this.secretKey = secretKey;
            this.apiKey = apiKey;
            this.signatureGenerator = new SignatureGenerator(apiKey, secretKey);
            baseURL = "https://api.ooyala.com";
            contentType = "application/json";
        } catch (NoSuchAlgorithmException e) {
            throw new OoyalaApiException(e);
        }
    }

    /**
     * Gets the Secret key
     *
     * @return the secret key
     */
    public String getSecretKey() {
        return secretKey;
    }

    /**
     * Sets the secret key
     *
     * @param secretKey The secret key to be set
     */
    public void setSecretKey(String secretKey) {
        this.secretKey = secretKey;
    }

    /**
     * Gets the API key
     *
     * @return the API key
     */
    public String getAPIKey() {
        return apiKey;
    }

    /**
     * Sets the API key
     *
     * @param apiKey The secret key to be set
     */
    public void setAPIKey(String apiKey) {
        this.apiKey = apiKey;
    }

    /**
     * Gets the URL where requests are sent
     *
     * @return the URL
     */
    public String getBaseURL() {
        return baseURL;
    }

    /**
     * Sets the URL where requests are sent
     *
     * @param baseURL The URL to be set
     * @return
     */
    public void setBaseURL(String baseURL) {
        this.baseURL = baseURL;
    }

    /**
     * Get the response code from previous request
     *
     * @return
     */
    public int getResponseCode() {
        return responseCode;
    }

    /**
     * Get the request's content type
     *
     * @return The request's content type
     */
    public String getContentType() {
        return contentType;
    }

    /**
     * Set the request's content type
     *
     * @param contentType The request's content type
     */
    public void setContentType(String contentType) {
        this.contentType = contentType;
    }

    /**
     * Response Handler
     *
     * @return
     */
    private ResponseHandler<String> createResponseHandler() {
        return new ResponseHandler<String>() {
            public String handleResponse(HttpResponse response) throws IOException {
                HttpEntity entity = response.getEntity();
                responseCode = response.getStatusLine().getStatusCode();
                if (entity != null) {
                    return EntityUtils.toString(entity);
                } else {
                    return null;
                }
            }
        };
    }

    /**
     * Sends a Request to the URL using the indicating HTTP method, content type and the array of bytes as body
     *
     * @param methodType  The HTTPMethod
     * @param URL         The URL where the request is made
     * @param requestBody The request's body as an array of bytes
     * @return The response from the server as an object of class JSON. Must be casted to either a LinkedList<String> or an HashMap<String, Object>
     * @throws OoyalaApiException
     * @throws HttpStatusCodeException
     */
    public JSON sendRequest(HttpMethodType methodType, String URL, byte[] requestBody)
            throws OoyalaApiException, HttpStatusCodeException {
        HttpRequestBase method = getHttpMethod(methodType, URL, new ByteArrayEntity(requestBody));

        try {
            return executeRequest(method);
        } catch (IOException e) {
            throw new OoyalaApiException(e);
        }
    }

    public JSON sendRequest(HttpMethodType methodType, String requestPath, HashMap<String, String> parameters)
            throws OoyalaApiException, HttpStatusCodeException {
        return sendRequest(methodType, requestPath, parameters, new HashMap<String, Object>());
    }

    /**
     * Creates a request to a given path using the indicated HTTP-Method with a (string) body
     *
     * @param methodType  The HTTP method (verb)
     * @param requestPath The request path
     * @param parameters  The query parameters
     * @param requestBody The request's body
     * @return The response from the server as an object of class Object. Must be casted to either a LinkedList<String> or an HashMap<String, Object>
     * @throws OoyalaApiException
     * @throws HttpStatusCodeException
     */
    @SuppressWarnings("rawtypes")
    public JSON sendRequest(HttpMethodType methodType, String requestPath, HashMap<String, String> parameters,
            HashMap<String, Object> requestBody) throws OoyalaApiException, HttpStatusCodeException {
        String jsonBody = "";

        if (requestBody != null && !requestBody.keySet().isEmpty()) {
            JSON jo = JSONSerializer.toJSON((Map) requestBody);
            jsonBody = jo.toString();
        }

        try {
            String url = generateURLWithAuthenticationParameters(methodType, getFixedRequestPath(requestPath),
                    parameters, jsonBody);
            HttpRequestBase method = getHttpMethod(methodType, url,
                    new StringEntity(jsonBody, HttpUtils.API_CHARSET));
            return executeRequest(method);
        } catch (NoSuchAlgorithmException e) {
            throw new OoyalaApiException(e);
        } catch (IOException e) {
            throw new OoyalaApiException(e);
        }
    }

    /**
     * Creates a request to a given path (requestPath) using the indicated HTTP-Method (HTTPMethod) wit neither
     * parameters nor a body (requestBody)
     *
     * @param methodType  The HTTP method
     * @param requestPath the request path
     * @return The response from the server as an object of class Object. Must be casted to either a LinkedList<String> or an HashMap<String, Object>
     * @throws OoyalaApiException
     * @throws HttpStatusCodeException
     */
    public JSON sendRequest(HttpMethodType methodType, String requestPath)
            throws OoyalaApiException, HttpStatusCodeException {
        return sendRequest(methodType, getFixedRequestPath(requestPath), new HashMap<String, String>(),
                new HashMap<String, Object>());
    }

    /**
     * Creates an instance of HttpRequestBase's subclass (HttpGet, HttpDelete, etc).
     *
     * @param methodType The HTTPMethod string name
     * @param URL        The URL
     * @param entity     the entity carrying the request's content
     * @return An instance of a HttpRequestBase's subclass
     */
    private HttpRequestBase getHttpMethod(HttpMethodType methodType, String URL, AbstractHttpEntity entity) {
        HttpRequestBase method = null;
        entity.setContentType(contentType);

        /* create the method object */
        switch (methodType) {
        case GET:
            method = new HttpGet(URL);
            break;
        case DELETE:
            method = new HttpDelete(URL);
            break;
        case POST:
            method = new HttpPost(URL);
            ((HttpPost) method).setEntity(entity);
            break;
        case PATCH:
            method = new HttpPatch(URL);
            ((HttpPatch) method).setEntity(entity);
            break;
        case PUT:
            method = new HttpPut(URL);
            ((HttpPut) method).setEntity(entity);
            break;
        }
        return method;
    }

    /**
     * Generate the URL including the authentication parameters
     *
     * @param methodType  The HTTP Method
     * @param requestPath The request's path
     * @param parameters  The query parameters
     * @param requestBody The string request body
     * @return
     * @throws NoSuchAlgorithmException
     * @throws IOException
     */
    @SuppressWarnings("unchecked")
    private String generateURLWithAuthenticationParameters(HttpMethodType methodType, String requestPath,
            HashMap<String, String> parameters, String requestBody) throws NoSuchAlgorithmException, IOException {
        HashMap<String, String> parametersWithAuthentication = (HashMap<String, String>) parameters.clone();

        String signature = signatureGenerator.generateSignature(methodType.toString(), requestPath,
                parametersWithAuthentication, requestBody, null);
        parametersWithAuthentication.put("signature", signature);
        return buildURL(methodType, requestPath, parametersWithAuthentication);
    }

    /**
     * Executes the request
     *
     * @param method The class containing the type of request (HttpGet, HttpDelete, etc)
     * @return The response from the server as an object of class Object. Must be casted to
     * either a LinkedList<String> or an HashMap<String, Object>
     * @throws IOException
     * @throws HttpStatusCodeException
     */
    @SuppressWarnings("unchecked")
    private JSON executeRequest(HttpRequestBase method) throws IOException, HttpStatusCodeException {
        try {
            System.out.println(String.format("%s\t%s", method.getMethod(), method.getURI().toASCIIString()));
            String response = httpClient.execute(method, createResponseHandler());

            if (!isResponseOK()) {
                throw new HttpStatusCodeException(response, getResponseCode());
            }

            if (response.isEmpty()) {
                return null;
            }

            return JSONSerializer.toJSON(response);
        } finally {
        }
    }

    /**
     * Creates a request to a given path using the indicated HTTP-Method with a (byte array) body
     *
     * @param methodType  The HTTP method (verb)
     * @param requestPath The request path
     * @param parameters  The query parameters
     * @param requestBody The request's body
     * @return The response from the server as an object of class Object. Must be casted to either
     * a LinkedList<String> or an HashMap<String, Object>
     * @throws OoyalaApiException
     * @throws HttpStatusCodeException
     */
    public JSON sendRequest(HttpMethodType methodType, String requestPath, HashMap<String, String> parameters,
            byte[] requestBody) throws OoyalaApiException, HttpStatusCodeException {
        try {
            String url = generateURLWithAuthenticationParameters(methodType, getFixedRequestPath(requestPath),
                    parameters, new String(requestBody, HttpUtils.API_CHARSET));
            HttpRequestBase method = getHttpMethod(methodType, url, new ByteArrayEntity(requestBody));
            return executeRequest(method);
        } catch (IOException e) {
            throw new OoyalaApiException(e);
        } catch (NoSuchAlgorithmException e) {
            throw new OoyalaApiException(e);
        }
    }

    /**
     * URI encodes non-authentication values
     *
     * @param parameters The hashtable containing values to URI encode
     * @return
     * @throws UnsupportedEncodingException
     */
    private HashMap<String, String> makeURIValues(HashMap<String, String> parameters)
            throws UnsupportedEncodingException {
        HashMap<String, String> URIParameters = new HashMap<String, String>();
        Set<String> set = parameters.keySet();
        Iterator<String> itr = set.iterator();
        while (itr.hasNext()) {
            String key = itr.next();
            String value = parameters.get(key);
            /* just URI encode non-authentication params*/
            if (!(key.equals("expires") || key.equals("api_key") || key.equals("signature"))) {
                URIParameters.put(key, HttpUtils.encodeURI(parameters.get(key)));
            } else
                URIParameters.put(key, value);
        }
        return URIParameters;
    }

    /**
     * Builds the URL for a given request. In the process, it includes the api_key, expires and signature parameters
     *
     * @param methodType  The HTTP method
     * @param requestPath The request path
     * @param parameters  The query parameters
     * @return The URL for a request.
     * @throws java.security.NoSuchAlgorithmException if the SHA256 algorithm is not
     *                                                available.
     * @throws java.io.UnsupportedEncodingException   if the Base64 encoder is not able
     *                                                to generate an output.
     */
    private String buildURL(HttpMethodType methodType, String requestPath, HashMap<String, String> parameters)
            throws java.security.NoSuchAlgorithmException, java.io.UnsupportedEncodingException {
        return String.format("%s%s?%s", baseURL, requestPath,
                HttpUtils.concatenateParams(makeURIValues(parameters), "&"));
    }

    /**
     * Sends a POST request
     *
     * @param requestPath The request path
     * @param requestBody The request's body
     * @return The response from the server as an object of class Object. Must be casted to either a LinkedList<String> or an HashMap<String, Object>
     * @throws OoyalaApiException
     * @throws HttpStatusCodeException
     */
    public JSON postRequest(String requestPath, HashMap<String, Object> requestBody)
            throws OoyalaApiException, HttpStatusCodeException {
        return sendRequest(HttpMethodType.POST, requestPath, new HashMap<String, String>(), requestBody);
    }

    /**
     * Sends a GET request
     *
     * @param requestPath The request path
     * @param parameters  hashtable containing query parameters
     * @return The response from the server as an object of class Object. Must be casted to either a LinkedList<String> or an HashMap<String, Object>
     * @throws OoyalaApiException
     * @throws HttpStatusCodeException
     */
    public JSON getRequest(String requestPath, HashMap<String, String> parameters)
            throws OoyalaApiException, HttpStatusCodeException {
        return sendRequest(HttpMethodType.GET, requestPath, parameters, new HashMap<String, Object>());
    }

    /**
     * Sends a GET request
     *
     * @param requestPath The request path
     * @return The response from the server as an object of class Object. Must be casted to either a LinkedList<String> or an HashMap<String, Object>
     * @throws OoyalaApiException
     * @throws HttpStatusCodeException
     */
    public JSON getRequest(String requestPath) throws OoyalaApiException, HttpStatusCodeException {
        return sendRequest(HttpMethodType.GET, requestPath);
    }

    /**
     * Sends a PUT request
     *
     * @param requestPath The request path
     * @param requestBody The request's body
     * @return The response from the server as an object of class Object. Must be casted to either a LinkedList<String> or an HashMap<String, Object>
     * @throws OoyalaApiException
     * @throws HttpStatusCodeException
     */
    public JSON putRequest(String requestPath, HashMap<String, Object> requestBody)
            throws OoyalaApiException, HttpStatusCodeException {
        return sendRequest(HttpMethodType.PUT, requestPath, new HashMap<String, String>(), requestBody);
    }

    /**
     * Sends a DELETE request
     *
     * @param requestPath The request path
     * @return The response from the server as an object of class Object. Must be casted to either a LinkedList<String> or an HashMap<String, Object>
     * @throws OoyalaApiException
     * @throws HttpStatusCodeException
     */
    public JSON deleteRequest(String requestPath) throws OoyalaApiException, HttpStatusCodeException {
        return sendRequest(HttpMethodType.DELETE, requestPath);
    }

    /**
     * Sends a PATCH request
     *
     * @param requestPath The request path
     * @param requestBody The patch to be sent
     * @return The response from the server as an object of class Object. Must be casted to either a LinkedList<String> or an HashMap<String, Object>
     * @throws OoyalaApiException
     * @throws HttpStatusCodeException
     */
    public JSON patchRequest(String requestPath, HashMap<String, Object> requestBody)
            throws OoyalaApiException, HttpStatusCodeException {
        return sendRequest(HttpMethodType.PATCH, requestPath, new HashMap<String, String>(), requestBody);
    }

    /**
     * This is to keep the api backward compatible, the /v2/ prefix was not needed in earlier versions, and baseURL
     * itself had /v2/ as part of it. But this wouldn't work with v3 api urls. So now requestPath needs to have /v2/
     * or /v3/ in it. If it is not present we add /v2/ prefix
     */
    private String getFixedRequestPath(String requestPath) {
        if (!requestPath.startsWith("/v2/") && !requestPath.startsWith("/v3/")) {
            requestPath = "/v2/" + requestPath;
        }
        return requestPath;
    }

    /**
     * Indicates if a request was successful
     *
     * @return
     */
    public boolean isResponseOK() {
        return ((responseCode >= 200) && (responseCode < 400));
    }

    /**
     * HttpPatch class which allows PATCH requests
     */
    private class HttpPatch extends HttpPost {
        public HttpPatch(String s) {
            super(s);
        }

        public String getMethod() {
            return HttpMethodType.PATCH.toString();
        }
    }
}