com.groupdocs.sdk.common.ApiInvoker.java Source code

Java tutorial

Introduction

Here is the source code for com.groupdocs.sdk.common.ApiInvoker.java

Source

/**
 *  Copyright 2012 GroupDocs.
 *
 *  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.groupdocs.sdk.common;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.ws.rs.core.MediaType;

import org.apache.commons.codec.binary.Base64InputStream;
import org.apache.commons.io.IOUtils;
import org.apache.sling.commons.mime.internal.MimeTypeServiceImpl;

import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.std.DateDeserializers.DateDeserializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource.Builder;
import com.sun.jersey.api.client.filter.LoggingFilter;
import com.sun.jersey.multipart.file.DefaultMediaTypePredictor;
import com.wordnik.swagger.core.util.JsonUtil;

public class ApiInvoker {
    public static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
    private static ApiInvoker INSTANCE = new ApiInvoker();
    private Map<String, Client> hostMap = new HashMap<String, Client>();
    private Map<String, String> defaultHeaderMap = new HashMap<String, String>();
    private static final String ENC = "UTF-8";
    private RequestSigner signer;
    private boolean isDebug;

    public static MimeTypeServiceImpl mimeTypeService = new MimeTypeServiceImpl();

    public static final String PACKAGE_NAME;
    public static final String PACKAGE_VERSION;

    static {
        Properties prop = new Properties();
        InputStream in = ApiInvoker.class.getResourceAsStream("/META-INF/application.properties");
        if (in != null) {
            try {
                prop.load(in);
            } catch (IOException e) {
            } finally {
                try {
                    in.close();
                } catch (IOException e) {
                }
            }
        }
        PACKAGE_NAME = prop.getProperty("application.name", "groupdocs-java");
        PACKAGE_VERSION = prop.getProperty("application.version", "unknown");
        try {
            mimeTypeService
                    .registerMimeType(ApiInvoker.class.getResourceAsStream(MimeTypeServiceImpl.CORE_MIME_TYPES));
        } catch (IOException e) {
            System.err.println("Failed to initialize MimeTypeServiceImpl");
        }
    }

    public static class CustomDateDeserializer extends DateDeserializer {
        public CustomDateDeserializer(DateDeserializer base) {
            super(base, new SimpleDateFormat(DATE_FORMAT), DATE_FORMAT);
        }
    }

    public static ApiInvoker getInstance() {
        return INSTANCE;
    }

    public void setDebug(boolean flag) {
        this.isDebug = flag;
    }

    public void setRequestSigner(RequestSigner signer) {
        this.signer = signer;
    }

    public void addDefaultHeader(String key, String value) {
        defaultHeaderMap.put(key, value);
    }

    public String escapeString(String str) {
        return encodeURIComponent(str);
    }

    public static String encodeURI(String uri) {
        return encodeURIComponent(uri).replace("%3B", ";").replace("%2C", ",").replace("%2F", "/")
                .replace("%3F", "?").replace("%3A", ":").replace("%40", "@").replace("%26", "&").replace("%3D", "=")
                //.replace("%2B", "+")
                .replace("%24", "$").replace("%25", "%").replace("%23", "#");
    }

    public static String encodeURIComponent(String str) {
        try {
            return URLEncoder.encode(str, ENC).replace("+", "%20").replace("%21", "!").replace("%27", "'")
                    .replace("%28", "(").replace("%29", ")").replace("%7E", "~");
        } catch (UnsupportedEncodingException e) {
            return str;
        }
    }

    @SuppressWarnings("unchecked")
    public static Object deserialize(String json, String containerType, @SuppressWarnings("rawtypes") Class cls)
            throws ApiException {
        try {
            ObjectMapper mapper = JsonUtil.getJsonMapper();
            SimpleModule m = new SimpleModule(PACKAGE_NAME, Version.unknownVersion());
            m.addDeserializer(Date.class, new CustomDateDeserializer(new DateDeserializer()));
            mapper.registerModule(m);

            if ("List".equals(containerType)) {
                JavaType typeInfo = mapper.getTypeFactory().constructCollectionType(List.class, cls);
                List<?> response = (List<?>) mapper.readValue(json, typeInfo);
                return response;
            } else if (String.class.equals(cls)) {
                return json;
            } else {
                return mapper.readValue(json, cls);
            }
        } catch (IOException e) {
            throw new ApiException(500, e.getMessage());
        }
    }

    public static String serialize(Object obj) throws ApiException {
        try {
            if (obj != null) {
                ObjectMapper jsonMapper = JsonUtil.getJsonMapper();
                jsonMapper.setSerializationInclusion(com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL);
                return jsonMapper.writeValueAsString(obj);
            } else
                return "";
        } catch (Exception e) {
            throw new ApiException(500, e.getMessage());
        }
    }

    @SuppressWarnings("unchecked")
    public <T> T invokeAPI(String host, String path, String method, Map<String, String> queryParams, Object body,
            Map<String, String> headerParams, Class<T> returnType) throws ApiException {
        Client client = getClient(host);

        StringBuilder b = new StringBuilder();

        for (String key : queryParams.keySet()) {
            String value = queryParams.get(key);
            if (value != null) {
                if (b.toString().length() == 0)
                    b.append("?");
                else
                    b.append("&");
                b.append(escapeString(key)).append("=").append(escapeString(value));
            }
        }
        String querystring = b.toString();

        boolean isFileUpload = false;
        MediaType contentType;
        if (body == null) {
            contentType = MediaType.TEXT_HTML_TYPE;
        } else {
            contentType = MediaType.APPLICATION_JSON_TYPE;
            if (body instanceof FileStream) {
                isFileUpload = true;
                contentType = MediaType.APPLICATION_OCTET_STREAM_TYPE;
            }
        }

        String requestUri = encodeURI(signer.signUrl(host + path + querystring)); //TODO incorrect for redirects
        Builder builder = client.resource(requestUri).type(contentType);
        builder.header("Groupdocs-Referer", PACKAGE_NAME + "/" + PACKAGE_VERSION);
        for (String key : headerParams.keySet()) {
            builder.header(key, headerParams.get(key));
        }

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

        if ("GET".equals(method)) {
            response = (ClientResponse) builder.get(ClientResponse.class);
        } else if ("POST".equals(method)) {
            Object requestBody;
            if (isFileUpload) {
                requestBody = ((FileStream) body).getInputStream();
            } else {
                requestBody = signer.signContent(serialize(body), builder);
            }
            response = builder.post(ClientResponse.class, requestBody);
        } else if ("PUT".equals(method)) {
            Object requestBody;
            if (isFileUpload) {
                requestBody = ((FileStream) body).getInputStream();
            } else {
                requestBody = signer.signContent(serialize(body), builder);
            }
            response = builder.put(ClientResponse.class, requestBody);
        } else if ("DELETE".equals(method)) {
            response = builder.delete(ClientResponse.class);
        } else {
            throw new ApiException(500, "unknown method type " + method);
        }
        if (response.getClientResponseStatus() == ClientResponse.Status.OK
                || response.getClientResponseStatus() == ClientResponse.Status.CREATED
                || response.getClientResponseStatus() == ClientResponse.Status.ACCEPTED) {
            T toReturn;
            if (FileStream.class.equals(returnType)) {
                if (response.getHeaders().containsKey("Transfer-Encoding") || response.getLength() > 0) {
                    toReturn = (T) new FileStream(requestUri, response);
                } else {
                    toReturn = null;
                }
            } else {
                toReturn = (T) response.getEntity(String.class);
            }
            return toReturn;
        } else {
            String errMsg = response.getEntity(String.class);
            try {
                HashMap<String, Object> props = JsonUtil.getJsonMapper().readValue(errMsg,
                        new TypeReference<HashMap<String, Object>>() {
                        });
                if (props.containsKey("error_message")) {
                    errMsg = (String) props.get("error_message");
                }
            } catch (IOException e) {
            }
            throw new ApiException(response.getClientResponseStatus().getStatusCode(), errMsg);
        }
    }

    /**
     * Read file contents into String according to http://en.wikipedia.org/wiki/Data_URI_scheme#Format
     * 
     * @param file
     * @return
    * @throws IOException 
    * @throws FileNotFoundException 
     * @throws Exception
     */
    public static String readAsDataURL(File file) throws IOException {
        String mimeType = mimeTypeService.getMimeType(file.getName());
        if (mimeType == null) {
            mimeType = new DefaultMediaTypePredictor().getMediaTypeFromFile(file).toString();
        }
        return readAsDataURL(file, mimeType);
    }

    public static String readAsDataURL(File file, String contentType) throws IOException {
        return readAsDataURL(new FileInputStream(file), contentType);
    }

    public static String readAsDataURL(InputStream is, String contentType) throws IOException {
        String base64file = IOUtils.toString(new Base64InputStream(is, true, 0, null));
        return "data:" + contentType + ";base64," + base64file;
    }

    private Client getClient(String host) {
        if (!hostMap.containsKey(host)) {
            Client client = Client.create();
            if (isDebug) {
                client.addFilter(new LoggingFilter());
            }
            hostMap.put(host, client);
        }
        return hostMap.get(host);
    }

}