org.kurento.jsonrpc.JsonRpcAndJavaMethodManager.java Source code

Java tutorial

Introduction

Here is the source code for org.kurento.jsonrpc.JsonRpcAndJavaMethodManager.java

Source

/*
 * (C) Copyright 2016 Kurento (http://kurento.org/)
 *
 * 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 org.kurento.jsonrpc;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import org.kurento.jsonrpc.message.Request;
import org.kurento.jsonrpc.message.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.thoughtworks.paranamer.AnnotationParanamer;
import com.thoughtworks.paranamer.Paranamer;

public class JsonRpcAndJavaMethodManager {

    private static final Logger log = LoggerFactory.getLogger(JsonRpcAndJavaMethodManager.class);

    private static Gson gson = new GsonBuilder().disableHtmlEscaping().create();

    private Paranamer paranamer = new AnnotationParanamer();

    public void executeMethod(Method m, Object object, Transaction transaction, Request<JsonObject> request)
            throws IOException {

        try {

            Response<JsonElement> response = execJavaMethod(transaction.getSession(), object, m, transaction,
                    request);

            if (response != null) {
                response.setId(request.getId());
                transaction.sendResponseObject(response);
            } else {
                transaction.sendVoidResponse();
            }

        } catch (InvocationTargetException e) {

            if (e.getCause() instanceof JsonRpcErrorException) {

                JsonRpcErrorException ex = (JsonRpcErrorException) e.getCause();

                transaction.sendError(ex.getError());

            } else {

                log.error("Exception executing request " + request + ": " + e.getCause().getLocalizedMessage(),
                        e.getCause());
                transaction.sendError(e.getCause());
            }

        } catch (Exception e) {
            log.error("Exception processing request " + request, e);
            transaction.sendError(e);
        }

    }

    private Response<JsonElement> execJavaMethod(Session session, Object object, Method m, Transaction transaction,
            Request<JsonObject> request)
            throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {

        Object[] values = calculateParamValues(session, m, request);

        Object result = m.invoke(object, values);

        if (result == null) {
            return null;
        } else {
            return new Response<>(null, gson.toJsonTree(result));
        }
    }

    private Object[] calculateParamValues(Session session, Method m, Request<JsonObject> request) {

        JsonObject params = request.getParams();

        String[] parameterNames = paranamer.lookupParameterNames(m, true);
        Type[] parameterTypes = m.getGenericParameterTypes();

        Object[] values = new Object[parameterTypes.length];
        for (int i = 0; i < parameterTypes.length; i++) {

            values[i] = getValueFromParam(session, m, params, parameterNames[i], parameterTypes[i]);
        }

        if (log.isInfoEnabled()) {
            StringBuilder sb = new StringBuilder("[");
            for (int i = 0; i < parameterNames.length; i++) {
                sb.append(parameterNames[i] + "(" + parameterTypes[i] + ")=" + values[i] + ",");
            }
            sb.append("]");

            log.debug("Executing method {} with params {}", m.getName(), params);
        }
        return values;
    }

    private Object getValueFromParam(Session session, Method m, JsonObject params, String parameterName,
            Type genericType) {

        if (genericType instanceof Class) {

            Class<?> type = (Class<?>) genericType;

            if (Session.class.isAssignableFrom(type)) {
                return session;
            } else {

                // TODO Allow more types
                JsonElement jsonElement = params.get(parameterName);

                if (jsonElement != null) {
                    return getAsJavaType(type, jsonElement);
                } else {
                    // TODO Fail in this case
                    if (type == boolean.class) {
                        return false;
                    } else if (type == int.class) {
                        return 0;
                    }
                }
            }

        } else {

            if (genericType instanceof ParameterizedType) {

                ParameterizedType genericMap = (ParameterizedType) genericType;

                if (Map.class.isAssignableFrom((Class<?>) genericMap.getRawType())
                        && (genericMap.getActualTypeArguments()[0] == String.class)
                        && (genericMap.getActualTypeArguments()[1] == String.class)) {

                    Map<String, String> returnParams = new HashMap<String, String>();
                    for (Entry<String, JsonElement> param : params.entrySet()) {
                        String valueStr = !param.getValue().isJsonNull() ? param.getValue().getAsString() : null;
                        returnParams.put(param.getKey(), valueStr);
                    }

                    return returnParams;
                }
            }
        }

        return null;
    }

    private Object getAsJavaType(Class<?> type, JsonElement jsonElement) {
        if (jsonElement.isJsonNull()) {
            return null;
        } else if (type == String.class) {
            return jsonElement.getClass().equals(JsonObject.class) ? jsonElement.toString()
                    : jsonElement.getAsString();
        } else if (type == boolean.class) {
            return jsonElement.getAsBoolean();
        } else if (type.isEnum()) {
            return gson.fromJson(jsonElement, type);
        } else if (type == int.class) {
            return jsonElement.getAsInt();
        } else {
            return null;
        }
    }
}