com.flexive.rest.client.FxRestClient.java Source code

Java tutorial

Introduction

Here is the source code for com.flexive.rest.client.FxRestClient.java

Source

/**
 * This file is part of the [fleXive](R) framework.
 *
 * Copyright (c) 1999-2013
 * UCS - unique computing solutions gmbh (http://www.ucs.at)
 * All rights reserved
 *
 * The [fleXive](R) project is free software; you can redistribute
 * it and/or modify it under the terms of the GNU Lesser General Public
 * License version 2.1 or higher as published by the Free Software Foundation.
 *
 * The GNU Lesser General Public License can be found at
 * http://www.gnu.org/licenses/lgpl.html.
 * A copy is found in the textfile LGPL.txt and important notices to the
 * license from the author are found in LICENSE.txt distributed with
 * these libraries.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * For further information about UCS - unique computing solutions gmbh,
 * please see the company website: http://www.ucs.at
 *
 * For further information about [fleXive](R), please see the
 * project website: http://www.flexive.org
 *
 *
 * This copyright notice MUST APPEAR in all copies of the file!
 */
package com.flexive.rest.client;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.flexive.rest.shared.FxRestApiResponse;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.annotation.ThreadSafe;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * A thread-safe connector to the flexive REST-API.
 *
 * @author Daniel Lichtenberger (daniel.lichtenberger@flexive.com), UCS - unique computing solutions gmbh (http://www.ucs.at)
 * @version $Rev$
 */
@ThreadSafe
public class FxRestClient {
    static final JsonFactory JSON_FACTORY = new JsonFactory();

    public static enum CallMethod {
        GET, POST
    }

    private final String apiBaseUrl;
    private final HttpClient client;

    public FxRestClient(String apiBaseUrl) {
        this.apiBaseUrl = apiBaseUrl.endsWith("/") ? apiBaseUrl.substring(0, apiBaseUrl.length() - 1) : apiBaseUrl;
        this.client = new DefaultHttpClient();
    }

    public String login(String username, String password) throws IOException {
        final HttpPost post = createCall(new HttpPost(), "/login");

        setPostParams(post, ImmutableMap.of("username", username, "password", password));

        final FxRestApiResponse response = parseResponse(client.execute(post));

        final String token = (String) response.getBody().get("token");

        if (StringUtils.isBlank(token)) {
            // should not happen
            throw new RuntimeException("No token and no error code returned from REST-API call");
        }

        return token;
    }

    @SuppressWarnings("unchecked")
    public RemoteMapSimple loadContent(String token, long id, int version) throws IOException {
        final HttpGet get = createCall(new HttpGet(), "/content/" + id + (version > 0 ? "." + version : ""));
        setRequestParameters(get, token);

        final FxRestApiResponse response = parseResponse(client.execute(get));

        return new RemoteMapSimple((Map<String, Object>) response.getBody().get("data"), true);
    }

    public RemoteMapSimple remoteCall(String token, String path, CallMethod method, Map<String, String> parameters)
            throws IOException {
        final HttpRequestBase request;
        if (method == CallMethod.GET) {
            final HttpGet httpGet = new HttpGet();
            if (parameters != null) {
                for (Map.Entry<String, String> entry : parameters.entrySet()) {
                    httpGet.getParams().setParameter(entry.getKey(), entry.getValue());
                }
            }
            request = httpGet;
        } else if (method == CallMethod.POST) {
            final HttpPost httpPost = new HttpPost();
            if (parameters != null) {
                setPostParams(httpPost, parameters);
            }
            request = httpPost;
        } else {
            throw new IllegalArgumentException("Method not supported: " + method);
        }
        setRequestParameters(request, token);

        final HttpRequestBase call = createCall(request, path);

        final FxRestApiResponse response = parseResponse(client.execute(call));

        return new RemoteMapSimple(response.getBody(), false);
    }

    @SuppressWarnings("unchecked")
    public RemoteFxSqlResult queryFxSql(String token, String query) throws IOException {
        final HttpPost post = createCall(new HttpPost(), "/query/fxsql");

        setRequestParameters(post, token);
        setPostParams(post, ImmutableMap.of("q", query));

        final FxRestApiResponse response = parseResponse(client.execute(post));

        final Map<String, Object> body = response.getBody();

        return new RemoteFxSqlResult((List<List<Object>>) body.get("rows"), (List<String>) body.get("columns"),
                (List<String>) body.get("columnLabels"));
    }

    private void setRequestParameters(HttpRequestBase request, String token) {
        if (StringUtils.isNotBlank(token)) {
            request.setHeader("token", token);
        }
    }

    private void setPostParams(HttpPost post, Map<String, String> params) {
        final List<NameValuePair> result = Lists.newArrayListWithCapacity(params.size());
        for (Map.Entry<String, String> entry : params.entrySet()) {
            result.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
        }
        try {
            post.setEntity(new UrlEncodedFormEntity(result));
        } catch (UnsupportedEncodingException e) {
            throw new IllegalStateException(e);
        }
    }

    private <T extends HttpRequestBase> T createCall(T request, String path) {
        request.setURI(URI.create(getApiUrl(path)));
        return request;
    }

    private String getApiUrl(String path) {
        return apiBaseUrl + path;
    }

    private void checkSuccess(FxRestApiResponse response) {
        final FxRestApiResponse.ResponseStatus status = response.getStatus();
        if (!status.isSuccess()) {
            throw new RemoteCallException(status.getCode(), status.getMessage());
        }
    }

    @SuppressWarnings("unchecked")
    private FxRestApiResponse parseResponse(HttpResponse httpResponse) throws IOException {
        try {
            final ObjectMapper mapper = new ObjectMapper(this.JSON_FACTORY);
            final FxRestApiResponse response = mapper.readValue(
                    this.JSON_FACTORY.createJsonParser(httpResponse.getEntity().getContent()),
                    FxRestApiResponse.class);
            if (response.getBody() == null) {
                response.setBody(Collections.<String, Object>emptyMap());
            }
            checkSuccess(response);
            return response;
        } finally {
            // release connection
            if (httpResponse.getEntity() != null) {
                httpResponse.getEntity().getContent().close();
            }
        }
    }
}