io.zbus.rpc.RpcProcessor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of zbus Show documentation
Show all versions of zbus Show documentation
a lightweight yet powerful MQ and RPC to build service bus
package io.zbus.rpc;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import io.zbus.kit.FileKit;
import io.zbus.kit.StrKit;
import io.zbus.kit.logging.Logger;
import io.zbus.kit.logging.LoggerFactory;
import io.zbus.transport.http.Message;
public class RpcProcessor {
private static final Logger log = LoggerFactory.getLogger(RpcProcessor.class);
private RpcCodec codec = new JsonRpcCodec();
private Map methods = new HashMap();
private Map> object2Methods = new HashMap>();
private String docUrlContext = "/";
public void addModule(Object... services){
for(Object obj : services){
if(obj == null) continue;
for(Class> intf : getAllInterfaces(obj.getClass())){
addModule(intf.getSimpleName(), obj);
addModule(intf.getName(), obj);
}
addModule(obj.getClass().getSimpleName(), obj);
addModule(obj.getClass().getName(), obj);
}
}
public void addModule(String module, Object... services){
for(Object service: services){
this.initCommandTable(module, service);
}
}
public void addModule(Class>... clazz){
Object[] services = new Object[clazz.length];
for(int i=0;i c = clazz[i];
try {
services[i] = c.newInstance();
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
addModule(services);
}
public void addModule(String module, Class>... clazz){
Object[] services = new Object[clazz.length];
for(int i=0;i c = clazz[i];
try {
services[i] = c.newInstance();
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
addModule(module, services);
}
public void removeModule(Object... services){
for(Object obj : services){
for(Class> intf : getAllInterfaces(obj.getClass())){
removeModule(intf.getSimpleName(), obj);
removeModule(intf.getCanonicalName(), obj);
}
removeModule(obj.getClass().getSimpleName(), obj);
removeModule(obj.getClass().getName(), obj);
}
}
public void removeModule(String module, Object... services){
for(Object service: services){
this.removeCommandTable(module, service);
}
}
private static List> getAllInterfaces(Class> clazz){
List> res = new ArrayList>();
while(clazz != null){
res.addAll(Arrays.asList(clazz.getInterfaces()));
clazz = clazz.getSuperclass();
}
return res;
}
private void addModuleInfo(String module, Object service){
List rpcMethods = null;
String serviceKey = service.getClass().getCanonicalName();
if(object2Methods.containsKey(serviceKey)){
rpcMethods = object2Methods.get(serviceKey);
} else {
rpcMethods = new ArrayList();
object2Methods.put(serviceKey,rpcMethods);
}
Method [] methods = service.getClass().getMethods();
for (Method m : methods) {
if(m.getDeclaringClass() == Object.class) continue;
String method = m.getName();
Remote cmd = m.getAnnotation(Remote.class);
if(cmd != null){
method = cmd.id();
if(cmd.exclude()) continue;
if("".equals(method)){
method = m.getName();
}
}
RpcMethod rpcm = null;
for(RpcMethod rm : rpcMethods) {
if(rm.getName().equals(method)) {
rpcm = rm;
break;
}
}
if(rpcm != null) {
if(!rpcm.modules.contains(module)) {
rpcm.modules.add(module);
}
} else {
List modules = new ArrayList();
modules.add(module);
rpcm = new RpcMethod();
rpcm.setModules(modules);
rpcm.setName(method);
rpcm.setReturnType(m.getReturnType().getCanonicalName());
List paramTypes = new ArrayList();
for(Class> t : m.getParameterTypes()){
paramTypes.add(t.getCanonicalName());
}
rpcm.setParamTypes(paramTypes);
rpcMethods.add(rpcm);
}
}
}
private void removeModuleInfo(Object service){
String serviceKey = service.getClass().getName();
object2Methods.remove(serviceKey);
}
private void initCommandTable(String module, Object service){
addModuleInfo(module, service);
try {
Method [] methods = service.getClass().getMethods();
for (Method m : methods) {
if(m.getDeclaringClass() == Object.class) continue;
String method = m.getName();
Remote cmd = m.getAnnotation(Remote.class);
if(cmd != null){
method = cmd.id();
if(cmd.exclude()) continue;
if("".equals(method)){
method = m.getName();
}
}
m.setAccessible(true);
MethodInstance mi = new MethodInstance(m, service);
String[] keys = paramSignature(module, m);
for(String key : keys){
if(this.methods.containsKey(key)){
log.debug(key + " overrided");
}
this.methods.put(key, mi);
}
}
} catch (SecurityException e) {
log.error(e.getMessage(), e);
}
}
private void removeCommandTable(String module, Object service){
removeModuleInfo(service);
try {
Method [] methods = service.getClass().getMethods();
for (Method m : methods) {
String method = m.getName();
Remote cmd = m.getAnnotation(Remote.class);
if(cmd != null){
method = cmd.id();
if(cmd.exclude()) continue;
if("".equals(method)){
method = m.getName();
}
}
String[] keys = paramSignature(module, m);
for(String key : keys){
this.methods.remove(key);
}
}
} catch (SecurityException e) {
log.error(e.getMessage(), e);
}
}
static class MethodMatchResult{
MethodInstance method;
boolean fullMatched;
}
private MethodMatchResult matchMethod(Request req){
StringBuilder sb = new StringBuilder();
if(req.getParamTypes() != null){
for(String type : req.getParamTypes()){
sb.append(type+",");
}
}
String module = req.getModule();
String method = req.getMethod();
String key = module+":"+method+":"+sb.toString();
String key2 = module+":"+method;
MethodMatchResult result = new MethodMatchResult();
if(this.methods.containsKey(key)){
result.method = this.methods.get(key);
result.fullMatched = true;
return result;
} else {
if(this.methods.containsKey(key2)){
result.method = this.methods.get(key2);
result.fullMatched = false;
return result;
}
String errorMsg = String.format("%s:%s not found, missing moudle settings?", module, method);
throw new IllegalArgumentException(errorMsg);
}
}
private String[] paramSignature(String module, Method m){
Class>[] paramTypes = m.getParameterTypes();
StringBuilder sb = new StringBuilder();
StringBuilder sb2 = new StringBuilder();
for(int i=0;i[] targetParamTypes = target.method.getParameterTypes();
int requiredLength = 0;
for(Class> clazz : targetParamTypes){
if(Message.class.isAssignableFrom(clazz)) continue; //ignore Message parameter
requiredLength++;
}
if(requiredLength != req.getParams().length){
String requiredParamTypeString = "";
for(int i=0;i paramType = targetParamTypes[i];
requiredParamTypeString += paramType.getName();
if(i" +
"%s " +
"%s(%s)
" +
" %s
" +
" %s" +
" " +
"" +
" %s
" +
" ";
String methodLink = docUrlContext + m.modules.get(0) + "/" + m.name;
String method = m.name;
String paramList = "";
for(String type : m.paramTypes) {
paramList += type + ", ";
}
if(paramList.length() > 0) {
paramList = paramList.substring(0, paramList.length()-2);
}
String paramDesc = "";
String methodDesc = "";
String modules = "";
for(String module : m.modules) {
modules += ""+module+" ";
}
return String.format(fmt, color, m.returnType, methodLink, method,
paramList, paramDesc, methodDesc, modules);
}
private Message renderDoc() throws IOException {
Message result = new Message();
String doc = "";
int rowIdx = 0;
for(List objectMethods : object2Methods.values()) {
for(RpcMethod m : objectMethods) {
doc += rowDoc(m, rowIdx++);
}
}
doc += " ";
Map model = new HashMap();
model.put("content", doc);
String body = FileKit.loadFile("rpc.htm", model);
result.setBody(body);
return result;
}
public Message process(Message msg){
String encoding = msg.getEncoding();
Object result = null;
int status = RpcCodec.STATUS_OK; //assumed to be successful
try {
Request req = codec.decodeRequest(msg);
if(req == null || StrKit.isEmpty(req.getMethod())){
return renderDoc();
} else {
MethodMatchResult matchResult = matchMethod(req);
MethodInstance target = matchResult.method;
if(matchResult.fullMatched){
checkParamTypes(target, req);
}
Class>[] targetParamTypes = target.method.getParameterTypes();
Object[] invokeParams = new Object[targetParamTypes.length];
Object[] reqParams = req.getParams();
int j = 0;
for(int i=0; i modules = new ArrayList();
private String name;
private List paramTypes = new ArrayList();
private String returnType;
public List getModules() {
return modules;
}
public void setModules(List modules) {
this.modules = modules;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List getParamTypes() {
return paramTypes;
}
public void setParamTypes(List paramTypes) {
this.paramTypes = paramTypes;
}
public String getReturnType() {
return returnType;
}
public void setReturnType(String returnType) {
this.returnType = returnType;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy