io.swagger.test.client.ApiClient.java Source code

Java tutorial

Introduction

Here is the source code for io.swagger.test.client.ApiClient.java

Source

/*
 *  Copyright 2016 SmartBear Software
 *
 *  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 io.swagger.test.client;

import com.fasterxml.jackson.databind.JavaType;
import io.swagger.test.client.auth.ApiKeyAuth;
import io.swagger.test.client.auth.Authentication;
import io.swagger.test.client.auth.HttpBasicAuth;
import io.swagger.test.client.auth.OAuth;
import io.swagger.util.Json;
import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.filter.LoggingFilter;
import org.glassfish.jersey.media.multipart.MultiPartFeature;

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.Invocation;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;

public class ApiClient {
    private Map<String, String> defaultHeaderMap = new HashMap<String, String>();
    private boolean debugging = false;
    private String basePath = "http://localhost:8080/api";

    private Map<String, Authentication> authentications;

    private DateFormat dateFormat;

    public ApiClient() {
        // Use ISO 8601 format for date and datetime.
        // See https://en.wikipedia.org/wiki/ISO_8601
        this.dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");

        // Use UTC as the default time zone.
        this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));

        // Set default User-Agent.
        setUserAgent("Java-Swagger");

        // Setup authentications (key: authentication name, value: authentication).
        authentications = new HashMap<String, Authentication>();
        authentications.put("api_key", new ApiKeyAuth("header", "api_key"));
        authentications.put("petstore_auth", new OAuth());
        // Prevent the authentications from being modified.
        authentications = Collections.unmodifiableMap(authentications);
    }

    public String getBasePath() {
        return basePath;
    }

    public ApiClient setBasePath(String basePath) {
        this.basePath = basePath;
        return this;
    }

    /**
     * Get authentications (key: authentication name, value: authentication).
     */
    public Map<String, Authentication> getAuthentications() {
        return authentications;
    }

    /**
     * Get authentication for the given name.
     *
     * @param authName The authentication name
     * @return The authentication, null if not found
     */
    public Authentication getAuthentication(String authName) {
        return authentications.get(authName);
    }

    /**
     * Helper method to set username for the first HTTP basic authentication.
     */
    public void setUsername(String username) {
        for (Authentication auth : authentications.values()) {
            if (auth instanceof HttpBasicAuth) {
                ((HttpBasicAuth) auth).setUsername(username);
                return;
            }
        }
        throw new RuntimeException("No HTTP basic authentication configured!");
    }

    /**
     * Helper method to set password for the first HTTP basic authentication.
     */
    public void setPassword(String password) {
        for (Authentication auth : authentications.values()) {
            if (auth instanceof HttpBasicAuth) {
                ((HttpBasicAuth) auth).setPassword(password);
                return;
            }
        }
        throw new RuntimeException("No HTTP basic authentication configured!");
    }

    /**
     * Helper method to set API key value for the first API key authentication.
     */
    public void setApiKey(String apiKey) {
        for (Authentication auth : authentications.values()) {
            if (auth instanceof ApiKeyAuth) {
                ((ApiKeyAuth) auth).setApiKey(apiKey);
                return;
            }
        }
        throw new RuntimeException("No API key authentication configured!");
    }

    /**
     * Helper method to set API key prefix for the first API key authentication.
     */
    public void setApiKeyPrefix(String apiKeyPrefix) {
        for (Authentication auth : authentications.values()) {
            if (auth instanceof ApiKeyAuth) {
                ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix);
                return;
            }
        }
        throw new RuntimeException("No API key authentication configured!");
    }

    /**
     * Set the User-Agent header's value (by adding to the default header map).
     */
    public ApiClient setUserAgent(String userAgent) {
        addDefaultHeader("User-Agent", userAgent);
        return this;
    }

    /**
     * Add a default header.
     *
     * @param key   The header's key
     * @param value The header's value
     */
    public ApiClient addDefaultHeader(String key, String value) {
        defaultHeaderMap.put(key, value);
        return this;
    }

    /**
     * Check that whether debugging is enabled for this API client.
     */
    public boolean isDebugging() {
        return debugging;
    }

    /**
     * Enable/disable debugging for this API client.
     *
     * @param debugging To enable (true) or disable (false) debugging
     */
    public ApiClient setDebugging(boolean debugging) {
        this.debugging = debugging;
        return this;
    }

    /**
     * Get the date format used to parse/format date parameters.
     */
    public DateFormat getDateFormat() {
        return dateFormat;
    }

    /**
     * Set the date format used to parse/format date parameters.
     */
    public ApiClient getDateFormat(DateFormat dateFormat) {
        this.dateFormat = dateFormat;
        return this;
    }

    /**
     * Parse the given string into Date object.
     */
    public Date parseDate(String str) {
        try {
            return dateFormat.parse(str);
        } catch (java.text.ParseException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Format the given Date object into string.
     */
    public String formatDate(Date date) {
        return dateFormat.format(date);
    }

    /**
     * Format the given parameter object into string.
     */
    public String parameterToString(Object param) {
        if (param == null) {
            return "";
        } else if (param instanceof Date) {
            return formatDate((Date) param);
        } else if (param instanceof Collection) {
            StringBuilder b = new StringBuilder();
            for (Object o : (Collection) param) {
                if (b.length() > 0) {
                    b.append(",");
                }
                b.append(String.valueOf(o));
            }
            return b.toString();
        } else {
            return String.valueOf(param);
        }
    }

    /**
     * Select the Accept header's value from the given accepts array:
     * if JSON exists in the given array, use it;
     * otherwise use all of them (joining into a string)
     *
     * @param accepts The accepts array to select from
     * @return The Accept header to use. If the given array is empty,
     * null will be returned (not to set the Accept header explicitly).
     */
    public String selectHeaderAccept(String[] accepts) {
        if (accepts.length == 0) {
            return null;
        }
        if (StringUtil.containsIgnoreCase(accepts, "application/json")) {
            return "application/json";
        }
        return StringUtil.join(accepts, ",");
    }

    /**
     * Select the Content-Type header's value from the given array:
     * if JSON exists in the given array, use it;
     * otherwise use the first one of the array.
     *
     * @param contentTypes The Content-Type array to select from
     * @return The Content-Type header to use. If the given array is empty,
     * JSON will be used.
     */
    public String selectHeaderContentType(String[] contentTypes) {
        if (contentTypes.length == 0) {
            return "application/json";
        }
        if (StringUtil.containsIgnoreCase(contentTypes, "application/json")) {
            return "application/json";
        }
        return contentTypes[0];
    }

    /**
     * Escape the given string to be used as URL query value.
     */
    public String escapeString(String str) {
        try {
            return URLEncoder.encode(str, "utf8").replaceAll("\\+", "%20");
        } catch (UnsupportedEncodingException e) {
            return str;
        }
    }

    /**
     * Deserialize the given JSON string to Java object.
     *
     * @param json          The JSON string
     * @param containerType The container type, one of "list", "array" or ""
     * @param cls           The type of the Java object
     * @return The deserialized Java object
     */
    public Object deserialize(String json, String containerType, Class cls) throws ApiException {
        if (null != containerType) {
            containerType = containerType.toLowerCase();
        }
        try {
            if ("list".equals(containerType) || "array".equals(containerType)) {
                JavaType typeInfo = Json.mapper().getTypeFactory().constructCollectionType(List.class, cls);
                List response = (List<?>) Json.mapper().readValue(json, typeInfo);
                return response;
            } else if (String.class.equals(cls)) {
                if (json != null && json.startsWith("\"") && json.endsWith("\"") && json.length() > 1) {
                    return json.substring(1, json.length() - 2);
                } else {
                    return json;
                }
            } else {
                return Json.mapper().readValue(json, cls);
            }
        } catch (IOException e) {
            throw new ApiException(500, e.getMessage(), null, json);
        }
    }

    private Entity<?> serialize(Object obj, String contentType) throws ApiException {
        try {
            if (obj != null) {
                if (contentType == null || MediaType.APPLICATION_JSON.equals(contentType)) {
                    return Entity.json(Json.mapper().writeValueAsString(obj));
                }
                return Entity.entity(obj, contentType);
            } else {
                return null;
            }
        } catch (Exception e) {
            throw new ApiException(500, e.getMessage());
        }
    }

    /**
     * Invoke API by sending HTTP request with the given options.
     *
     * @param path         The sub-path of the HTTP URL
     * @param method       The request method, one of "GET", "POST", "PUT", and "DELETE"
     * @param queryParams  The query parameters
     * @param body         The request body object
     * @param headerParams The header parameters
     * @param formParams   The form parameters
     * @param accept       The request's Accept header
     * @param contentType  The request's Content-Type header
     * @param authNames    The authentications to apply
     * @return The response body in type of string
     */
    public String invokeAPI(String path, String method, Map<String, String> queryParams, Object body,
            Map<String, String> headerParams, Entity<?> formParams, String accept, String contentType,
            String[] authNames) throws ApiException {
        updateParamsForAuth(authNames, queryParams, headerParams);

        final ClientConfig clientConfig = new ClientConfig();
        clientConfig.register(MultiPartFeature.class);
        if (debugging) {
            clientConfig.register(LoggingFilter.class);
        }
        Client client = ClientBuilder.newClient(clientConfig);

        WebTarget target = client.target(this.basePath).path(path);

        for (String key : queryParams.keySet()) {
            String value = queryParams.get(key);
            if (value != null) {
                target = target.queryParam(key, value);
            }
        }

        Invocation.Builder invocationBuilder = target.request(contentType);

        for (String key : headerParams.keySet()) {
            String value = headerParams.get(key);
            if (value != null) {
                invocationBuilder = invocationBuilder.header(key, value);
            }
        }

        for (String key : defaultHeaderMap.keySet()) {
            if (!headerParams.containsKey(key)) {
                String value = defaultHeaderMap.get(key);
                if (value != null) {
                    invocationBuilder = invocationBuilder.header(key, value);
                }
            }
        }
        Response response = null;

        invocationBuilder = invocationBuilder.accept(accept);

        if ("GET".equals(method)) {
            response = invocationBuilder.get();
        } else if ("POST".equals(method)) {
            if (formParams != null) {
                response = invocationBuilder.post(formParams);
            } else if (body == null) {
                response = invocationBuilder.post(null);
            } else {
                response = invocationBuilder.post(serialize(body, contentType));
            }
        } else if ("PUT".equals(method)) {
            if (formParams != null) {
                response = invocationBuilder.put(formParams);
            } else if (body == null) {
                response = invocationBuilder.put(null);
            } else {
                response = invocationBuilder.put(serialize(body, contentType));
            }
        } else if ("DELETE".equals(method)) {
            response = invocationBuilder.delete();
        } else {
            throw new ApiException(500, "unknown method type " + method);
        }

        if (response.getStatus() == Status.NO_CONTENT.getStatusCode()) {
            return null;
        } else if (response.getStatusInfo().getFamily().equals(Status.Family.SUCCESSFUL)) {
            if (response.hasEntity()) {
                return (String) response.readEntity(String.class);
            } else {
                return "";
            }
        } else {
            String message = "error";
            String respBody = null;
            Map<String, List<String>> responseHeaders = new HashMap<String, List<String>>();
            for (String key : response.getHeaders().keySet()) {
                List<Object> values = response.getHeaders().get(key);
                for (Object o : values) {
                    List<String> headers = responseHeaders.get(key);
                    if (headers == null) {
                        headers = new ArrayList<String>();
                        responseHeaders.put(key, headers);
                    }
                    headers.add(String.valueOf(o));
                }
            }

            if (response.hasEntity()) {
                try {
                    message = String.valueOf(response.readEntity(String.class));
                } catch (RuntimeException e) {
                    // e.printStackTrace();
                }
            }
            throw new ApiException(response.getStatusInfo().getStatusCode(), message, responseHeaders, respBody);
        }
    }

    /**
     * Update query and header parameters based on authentication settings.
     *
     * @param authNames The authentications to apply
     */
    private void updateParamsForAuth(String[] authNames, Map<String, String> queryParams,
            Map<String, String> headerParams) {
        for (String authName : authNames) {
            Authentication auth = authentications.get(authName);
            if (auth == null) {
                throw new RuntimeException("Authentication undefined: " + authName);
            }
            auth.applyToParams(queryParams, headerParams);
        }
    }
}