All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.wordnik.swagger.runtime.common.APIInvoker Maven / Gradle / Ivy

/**
 *  Copyright 2015 Reverb Technologies, 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.wordnik.swagger.runtime.common;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.String;
import java.net.URLEncoder;
import java.util.Map;
import java.util.List;
import java.util.HashMap;
import java.util.logging.Logger;

import com.wordnik.swagger.runtime.exception.APIException;
import com.wordnik.swagger.runtime.exception.APIExceptionCodes;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.DeserializationConfig.Feature;
import org.codehaus.jackson.map.SerializationConfig;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.WebResource.Builder;
import com.sun.jersey.api.client.filter.LoggingFilter;


/**
 * Provides method to initialize the api server settings and also handles the logic related to invoking the API server
 * along with serealizing and deserializing input and output responses.
 *
 * This is also a Base class for all API classes
 *
 * @author ramesh
 *
 */
public class APIInvoker {

	private String apiServer = "http://api.wordnik.com/v4";
	private SecurityHandler securityHandler = null;
	private static boolean loggingEnabled;
	private static Logger logger = null;
	private static APIInvoker apiInvoker = null;
    private static Client apiClient = null;

	protected static String POST = "POST";
	protected static String GET = "GET";
	protected static String PUT = "PUT";
	protected static String DELETE = "DELETE";
	public static ObjectMapper mapper = new ObjectMapper();
	static{
        mapper.getDeserializationConfig().set(Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.getSerializationConfig().set(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false);
        mapper.configure(SerializationConfig.Feature.WRITE_NULL_PROPERTIES, false);
        mapper.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, false);
        apiClient = Client.create();
	}

	/**
	 * Initializes the API communication with required inputs. 
	 * @param securityHandler security handler responsible for populating necessary security invocation while making API server calls
	 * @param apiServer Sets the URL for the API server. It is defaulted to the server 
	 * 					used while building the driver. This value should be provided while testing the APIs against 
	 * 					test servers or if there is any changes in production server URLs.
	 * @param enableLogging This will enable the logging using Jersey logging filter. Refer the following documentation 
	 * 						for more details. {@link com.sun.jersey.api.client.filter.LoggingFilter}. Default output is sent to system.out.
	 * 						Create a logger ({@link java.util.logging.Logger} class and set using setLogger method.
	 */
	public static APIInvoker initialize(SecurityHandler securityHandler, String apiServer, boolean enableLogging) {
        APIInvoker invoker = new APIInvoker();
		invoker.setSecurityHandler(securityHandler);
		if(apiServer != null && apiServer.length() > 0) {
			if(apiServer.substring(apiServer.length()-1).equals("/")){
				apiServer = apiServer.substring(0, apiServer.length()-1);
			}
			invoker.setApiServer(apiServer);
		}
		invoker.setLoggingEnable(enableLogging);
        //initialize the logger if needed
        if(loggingEnabled) {
        	if(logger == null) {
        		apiClient.addFilter(new LoggingFilter());
        	}else{
        		apiClient.addFilter(new LoggingFilter(logger));
        	}
        }
        apiInvoker = invoker;
        return invoker;
	}

    /**
     * Returns lst initialized API invoker
     * @return
     */
    public static APIInvoker getApiInvoker(){
        return apiInvoker;
    }

	/**
	 * Set the logger instance used for Jersey logging. 
	 * @param aLogger
	 */
	public void setLogger(Logger aLogger) {
		logger = aLogger; 
	}
	
	/**
	 * Gets the API key used for server communication. 
	 * This value is set using initialize method. 
	 * @return
	 */
	public SecurityHandler setSecurityHandler() {
		return securityHandler;
	}

	private void setSecurityHandler(SecurityHandler aSecurityHandler) {
		securityHandler = aSecurityHandler;
	}

	/**
	 * Sets the URL for the API server. It is defaulted to the server used while building the driver.
	 * @return 
	 */
	private String getApiServer() {
		return apiServer;
	}

	public void setApiServer(String server) {
		apiServer = server;
	}
	
	
	
	/**
	 * Invokes the API and returns the response as json string.
     *
	 * This is an internal method called by individual APIs for communication. It sets the required security information
     * based ons ecuroty handler
	 *
	 * @param resourceURL - URL for the rest resource
	 * @param method - Method we should use for communicating to the back end. 
	 * @param postData - if the method is POST, provide the object that should be sent as part of post request.
	 * @return JSON response of the API call. 
	 * @throws com.wordnik.swagger.runtime.exception.APIException if the call to API server fails.
	 */
	public String invokeAPI(String resourceURL, String method, Map queryParams, Object postData, Map headerParams) throws APIException {


        //check for app server values
        if(getApiServer() == null || getApiServer().length() == 0) {
        	String[] args = {getApiServer()};
        	throw new APIException(APIExceptionCodes.API_SERVER_NOT_VALID, args);
        }

        //make the communication
		resourceURL = getApiServer() + resourceURL;
		if(queryParams.keySet().size() > 0){
			int i=0;
			for(String paramName : queryParams.keySet()){
				String symbol = "&";
				if(i==0){
					symbol = "?";
				}
				resourceURL = resourceURL + symbol + paramName + "=" + queryParams.get(paramName);
				i++;
			}
		}
        Map headerMap = new HashMap();
        if(securityHandler != null){
            securityHandler.populateSecurityInfo(resourceURL, headerMap);
        }
        WebResource aResource = apiClient.resource(resourceURL);


        //set the required HTTP headers
        Builder builder = aResource.type("application/json");
        for(String key : headerMap.keySet()){
            builder.header(key, headerMap.get(key));
        }
        if(headerParams != null){
            for(String key : headerParams.keySet()){
                builder.header(key, headerParams.get(key));
            }
        }

        ClientResponse clientResponse = null;
        if(method.equals(GET)) {
        	clientResponse =  builder.get(ClientResponse.class);
        }else if (method.equals(POST)) {
        	clientResponse =  builder.post(ClientResponse.class, serialize(postData));
        }else if (method.equals(PUT)) {
        	clientResponse =  builder.put(ClientResponse.class, serialize(postData));
        }else if (method.equals(DELETE)) {
        	clientResponse =  builder.delete(ClientResponse.class);
        }
        
        //process the response
        if(clientResponse.getClientResponseStatus() == ClientResponse.Status.OK) {
	        String response = clientResponse.getEntity(String.class);
			return response;
        }else{
        	int responseCode = clientResponse.getClientResponseStatus().getStatusCode() ;
        	throw new APIException(responseCode, clientResponse.getEntity(String.class));
        }
	}
	
	/**
	 * De-serialize the object from String to object of type input class name.
	 * @param response
	 * @param inputClassName
	 * @return
	 */
	public static Object deserialize(String response, Class inputClassName) throws APIException {
        try {
            if(inputClassName.isAssignableFrom(String.class)){
                return response;
            } else if (inputClassName.isAssignableFrom(Integer.class)){
                return new Integer(response);
            } else if (inputClassName.isAssignableFrom(Boolean.class)){
                return new Boolean(response);
            } else if (inputClassName.isAssignableFrom(Long.class)){
                return new Long(response);
            } else if (inputClassName.isAssignableFrom(Double.class)){
                return new Double(response);
            } else{
                Object responseObject = mapper.readValue(response, inputClassName);
                return responseObject;
            }
        } catch (IOException ioe) {
        	String[] args = new String[]{response, inputClassName.toString()};
            throw new APIException(APIExceptionCodes.ERROR_CONVERTING_JSON_TO_JAVA, args, "Error in coversting response json value to java object : " + ioe.getMessage(), ioe);
        }
	}


	/**
	 * serialize the object from String to input object. 
	 * @param input
	 * @return
	 */
	public static String serialize(Object input) throws APIException {
        try {
        	if(input != null) {
	            return mapper.writeValueAsString(input);
        	}else{
        		return "";
        	}
        } catch (IOException ioe) {
            throw new APIException(APIExceptionCodes.ERROR_CONVERTING_JAVA_TO_JSON, "Error in coverting input java to json : " + ioe.getMessage(), ioe);
        }
	}


    /**
     * Overloaded method for returning the path value
     * For a string value an empty value is returned if the value is null
     * @param value
     * @return
     */
    public static String toPathValue(String value) {
        value = (value == null) ? "" : value;
        return encode(value);
    }

    /**
     * Overloaded method for returning a path value
     * For a list of objects a comma separated string is returned
     * @param objects
     * @return
     */
    public static String toPathValue(List objects) {
        StringBuilder out = new StringBuilder();
        String output = "";
        for(Object o: objects){
            out.append(o.toString());
            out.append(",");
        }
        if(out.indexOf(",") != -1) {
            output = out.substring(0, out.lastIndexOf(",") );
        }
        return encode(output);
    }

    private static String encode(String value){
        try{
            return URLEncoder.encode(value, "utf-8").replaceAll("\\+", "%20");
        }catch(UnsupportedEncodingException uee){
            throw new RuntimeException(uee.getMessage());
        }
    }

    public boolean isLoggingEnable() {
        return loggingEnabled;
    }

    public void setLoggingEnable(boolean enabled) {
        loggingEnabled = enabled;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy