package com.yiqiniu.easytrans.rpc.impl.dubbo;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.ServiceConfig;
import com.alibaba.dubbo.rpc.service.GenericException;
import com.alibaba.dubbo.rpc.service.GenericService;
import com.yiqiniu.easytrans.config.EasyTransConifg;
import com.yiqiniu.easytrans.filter.EasyTransFilter;
import com.yiqiniu.easytrans.filter.EasyTransFilterChainFactory;
import com.yiqiniu.easytrans.protocol.BusinessIdentifer;
import com.yiqiniu.easytrans.protocol.RpcBusinessProvider;
import com.yiqiniu.easytrans.rpc.EasyTransRpcProvider;
public class DubboEasyTransRpcProviderImpl implements EasyTransRpcProvider{
@Resource
EasyTransFilterChainFactory filterChainFactory;
private List<EasyTransFilter> filters = new ArrayList<EasyTransFilter>();
@Resource
private EasyTransConifg easyTransConfig;
private static DubboEasyTransRpcProviderImpl injectHelper;
@PostConstruct
private void init(){
injectHelper = this;
}
public static DubboEasyTransRpcProviderImpl getInstance(){
return injectHelper;
}
public EasyTransFilterChainFactory getFilterChainFactory() {
return filterChainFactory;
}
public List<EasyTransFilter> getFilters() {
return new ArrayList<EasyTransFilter>(filters);
}
@Override
public void startService(Class<?> businessInterface,Map<BusinessIdentifer, RpcBusinessProvider<?>> businessList) {
for(Entry<BusinessIdentifer, RpcBusinessProvider<?>> entry :businessList.entrySet()){
BusinessIdentifer key = entry.getKey();
final RpcBusinessProvider<?> value = entry.getValue();
GenericService genericService = new GenericService() {
@Override
public Object $invoke(String method, String[] parameterTypes, Object[] args)
throws GenericException {
Method callMethod = getMethod(value.getClass(),method,parameterTypes);
try {
return callMethod.invoke(value, args);
} catch (IllegalAccessException | IllegalArgumentException
| InvocationTargetException e) {
throw new RuntimeException(e);
}
}
};
ServiceConfig<GenericService> service = new ServiceConfig<GenericService>();
service.setInterface(businessInterface);
service.setGroup(key.appId() + "-" + key.busCode());
service.setVersion("1.0.0");
service.setRef(genericService);
service.setCluster("failfast");
service.setApplication(new ApplicationConfig(easyTransConfig.getAppId()));
service.setRegistry(new RegistryConfig(easyTransConfig.getExtendConfig("zookeeper.url")));
int rpcTimeOut = key.rpcTimeOut();
if(rpcTimeOut == 0){
String timeoutString = easyTransConfig.getExtendConfig("dubbo.timeout.default");
if(timeoutString != null){
service.setTimeout(Integer.valueOf(timeoutString));
}
}else{
service.setTimeout(key.rpcTimeOut());
}
service.setFilter("easyTransFilter");
service.export();
}
}
private ConcurrentHashMap<String, Method> mapMethod = new ConcurrentHashMap<String, Method>();
private Method getMethod(Class<?> clazz,String method, String[] parameterTypes) {
String methodKey = getKey(clazz,method,parameterTypes);
Method result = mapMethod.get(methodKey);
if (result == null) {
try {
Class<?>[] params = new Class<?>[parameterTypes.length];
for (int i = 0; i < params.length; i++) {
params[i] = Class.forName(parameterTypes[i]);
}
result = clazz.getMethod(method, params);
mapMethod.put(methodKey, result);
} catch (ClassNotFoundException | NoSuchMethodException | SecurityException e) {
throw new RuntimeException(e);
}
}
return result;
}
private String getKey(Class<?> clazz, String method, String[] parameterTypes) {
StringBuilder sb = new StringBuilder(clazz.getName());
sb.append(method);
if(parameterTypes != null){
for(String s:parameterTypes){
sb.append(s);
}
}
return sb.toString();
}
@Override
public void addEasyTransFilter(List<EasyTransFilter> filters) {
this.filters.addAll(filters);
}
}