package com.ustcinfo.rpc.server;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ustcinfo.rpc.RequestWrapper;
import com.ustcinfo.rpc.ResponseWrapper;
import com.ustcinfo.rpc.annotation.Codecs;
public class RPCServerHandler implements ServerHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(RPCServerHandler.class);
// Server Processors key: servicename value: service instance
private static Map<String, Object> processors = new HashMap<String, Object>();
// Cached Server Methods key: instanceName#methodname$argtype_argtype
private static Map<String, Method> cacheMethods = new HashMap<String, Method>();
public void registerProcessor(String instanceName,Object instance){
processors.put(instanceName, instance);
Class<?> instanceClass = instance.getClass();
Method[] methods = instanceClass.getMethods();
for (Method method : methods) {
Class<?>[] argTypes = method.getParameterTypes();
StringBuilder methodKeyBuilder = new StringBuilder();
methodKeyBuilder.append(instanceName).append("#");
methodKeyBuilder.append(method.getName()).append("$");
for (Class<?> argClass : argTypes) {
methodKeyBuilder.append(argClass.getName()).append("_");
}
cacheMethods.put(methodKeyBuilder.toString(), method);
}
}
public ResponseWrapper handleRequest(final RequestWrapper request){
ResponseWrapper responseWrapper = new ResponseWrapper(request.getId(),request.getCodecType());
String targetInstanceName = new String(request.getTargetInstanceName());
String methodName = new String(request.getMethodName());
byte[][] argTypeBytes = request.getArgTypes();
String[] argTypes = new String[argTypeBytes.length];
for(int i = 0; i <argTypeBytes.length; i++) {
argTypes[i] = new String(argTypeBytes[i]);
}
Object[] requestObjects = null;
Method method = null;
try{
Object processor = processors.get(targetInstanceName);
if(processor == null){
throw new Exception("no "+targetInstanceName+" instance exists on the server");
}
if (argTypes != null && argTypes.length > 0) {
StringBuilder methodKeyBuilder = new StringBuilder();
methodKeyBuilder.append(targetInstanceName).append("#");
methodKeyBuilder.append(methodName).append("$");
Class<?>[] argTypeClasses = new Class<?>[argTypes.length];
for (int i = 0; i < argTypes.length; i++) {
methodKeyBuilder.append(argTypes[i]).append("_");
argTypeClasses[i] = Class.forName(argTypes[i]);
}
requestObjects = new Object[argTypes.length];
method = cacheMethods.get(methodKeyBuilder.toString());
if(method == null){
throw new Exception("no method: "+methodKeyBuilder.toString()+" find in "+targetInstanceName+" on the server");
}
Object[] tmprequestObjects = request
.getRequestObjects();
for (int i = 0; i < tmprequestObjects.length; i++) {
try{
requestObjects[i] = Codecs.getDecoder(request.getCodecType()).decode(argTypes[i],(byte[])tmprequestObjects[i]);
}
catch(Exception e){
throw new Exception("decode request object args error",e);
}
}
}
else {
method = processor.getClass().getMethod(methodName,
new Class<?>[] {});
if(method == null){
throw new Exception("no method: "+methodName+" find in "+targetInstanceName+" on the server");
}
requestObjects = new Object[] {};
}
responseWrapper.setResponse(method.invoke(processor, requestObjects));
}
catch(Exception e){
LOGGER.error("server handle request error",e);
responseWrapper.setException(e);
}
return responseWrapper;
}
}