com.github.dactiv.fear.service.RemoteApiCaller.java Source code

Java tutorial

Introduction

Here is the source code for com.github.dactiv.fear.service.RemoteApiCaller.java

Source

/*
 * Copyright 2015 dactiv
 *
 * 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.github.dactiv.fear.service;

import com.github.dactiv.fear.commons.ApiCaller;
import com.github.dactiv.fear.commons.result.ApiResult;
import com.github.dactiv.fear.commons.result.support.ErrorApiResult;
import com.github.dactiv.fear.commons.result.support.SimpleApiResult;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Method;
import java.util.Date;
import java.util.Map;

/**
 *
 * RMI ? Api 
 *
 * @author maurice
 */
@Component
public class RemoteApiCaller implements ApiCaller {

    private final static Logger LOGGER = LoggerFactory.getLogger(RemoteApiCaller.class);

    @Autowired
    private ApplicationContext applicationContext;
    // ?
    private Map<String, Map<String, Method>> serviceCache = Maps.newConcurrentMap();

    /**
     * ?
     *
     * @param serviceName ???
     * @param methodName  ??
     * @param params      ?
     *
     * @return 
     */
    @Override
    public ApiResult invoke(String serviceName, String methodName, Object... params) {

        SimpleApiResult simpleApiResult = new SimpleApiResult(new Date());

        try {
            LOGGER.info("? " + serviceName + " ?");
            Object bean = applicationContext.getBean(serviceName);

            Method method = getService(bean.getClass(), methodName, params);

            if (method == null) {
                method = findService(bean.getClass(), methodName, params);
            }

            // ??
            if (method == null) {
                return new ErrorApiResult(simpleApiResult.getInvokeDate(),
                        "?" + serviceName + "?" + methodName + "", ApiResult.NOT_FOUND,
                        new Date());
            }
            LOGGER.info(" " + serviceName + " ? " + method.getName() + " ");
            // 
            Object data = ReflectionUtils.invokeMethod(method, bean, params);
            // ? null, ? json 
            if (data != null) {
                simpleApiResult.setData(data);
            }
            // ?
            simpleApiResult.setCompleteDate(new Date());
            LOGGER.info("? " + bean.getClass().getName() + "." + method.getName() + " ");
            return simpleApiResult;
        } catch (Exception e) {
            LOGGER.error(" api ", e);
            return new ErrorApiResult(simpleApiResult.getInvokeDate(), e, ApiResult.ERROR, new Date());
        }
    }

    /**
     * ?
     *
     * @param targetClass  class
     * @param method ??
     * @param params ?
     *
     * @return 
     */
    public Method findService(Class<?> targetClass, String method, Object... params) {

        if (ArrayUtils.isNotEmpty(params)) {

            Class<?>[] paramTypes = convertParamToClass(params);

            return findParamMethod(targetClass, method, paramTypes);

        } else {
            return ReflectionUtils.findMethod(targetClass, method);
        }
    }

    /**
     * ??
     *
     * @param targetClass  class
     * @param method      ??
     * @param paramTypes  ?
     *
     * @return 
     */
    private Method findParamMethod(Class<?> targetClass, String method, Class<?>[] paramTypes) {

        // ?
        Method[] methods = (targetClass.isInterface() ? targetClass.getMethods()
                : ReflectionUtils.getAllDeclaredMethods(targetClass));

        // ?
        for (Method m : methods) {
            // ??
            Class<?>[] methodParamTypes = m.getParameterTypes();
            // ??????
            if (m.getName().equals(method) && methodParamTypes.length == paramTypes.length) {
                // ??
                Boolean flag = Boolean.TRUE;
                // ??flag  true
                for (int i = 0; i < methodParamTypes.length; i++) {

                    Class<?> paramTarget = paramTypes[i];
                    Class<?> paramSource = methodParamTypes[i];

                    if (paramTarget != null && paramTarget != paramSource
                            && !paramSource.isAssignableFrom(paramTarget)) {
                        flag = Boolean.FALSE;
                    }

                }

                if (flag) {
                    cacheService(targetClass, m, paramTypes);
                    return m;
                }

            }

        }

        return null;
    }

    /**
     * ?
     *
     * @param targetClass  class
     * @param method      
     * @param paramTypes  ???
     */
    private void cacheService(Class<?> targetClass, Method method, Class<?>[] paramTypes) {

        String targetName = targetClass.getName();

        if (!serviceCache.containsKey(targetName)) {
            serviceCache.put(targetName, Maps.<String, Method>newLinkedHashMap());
        }

        Map<String, Method> methodMap = serviceCache.get(targetName);

        String methodKey = getKey(method.getName(), paramTypes);

        if (!methodMap.containsKey(methodKey)) {
            methodMap.put(methodKey, method);
        }
    }

    /**
     * ??
     *
     * @param targetClass  class
     * @param methodName  ??
     * @param params      ??
     *
     * @return ??
     */
    private Method getService(Class<?> targetClass, String methodName, Object... params) {

        String targetName = targetClass.getName();

        if (!serviceCache.containsKey(targetName)) {
            return null;
        }

        Class<?>[] paramTypes = convertParamToClass(params);

        String methodKey = getKey(methodName, paramTypes);

        Map<String, Method> methodMap = serviceCache.get(targetName);

        return methodMap.containsKey(methodKey) ? methodMap.get(methodKey) : null;
    }

    /**
     * ?? class 
     *
     * @param params ?
     *
     * @return class 
     */
    private Class<?>[] convertParamToClass(Object... params) {
        Class<?>[] paramTypes = new Class<?>[params.length];

        for (int i = 0; i < paramTypes.length; i++) {

            Object value = params[i];

            if (value != null) {
                paramTypes[i] = params[i].getClass();
            } else {
                paramTypes[i] = null;
            }

        }

        return paramTypes;
    }

    /**
     * ???? key
     *
     * @param methodName ??
     * @param paramTypes ?
     *
     * @return  key
     */
    private String getKey(String methodName, Class<?>[] paramTypes) {

        StringBuilder builder = new StringBuilder("_");

        for (Class<?> type : paramTypes) {
            if (type != null) {
                builder.append(type.getName()).append("_");
            }
        }

        return methodName + builder.toString();
    }

}