package com.bluedavy.rpc.server;
/**
* nfs-rpc
* Apache License
*
* http://code.google.com/p/nfs-rpc (c) 2011
*/
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.bluedavy.rpc.Coders;
import com.bluedavy.rpc.RequestWrapper;
import com.bluedavy.rpc.ResponseWrapper;
/**
* MethodHandle RPC Server Handler
*
* @author <a href="mailto:bluedavy@gmail.com">bluedavy</a>
*/
public class RPCJava7ServerHandler implements ServerHandler {
// 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, MethodHandle> cachedMethodHandles = new HashMap<String, MethodHandle>();
/* (non-Javadoc)
* @see com.bluedavy.rpc.ServerHandler#registerProcessor(java.lang.String, java.lang.Object)
*/
@Override
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("_");
}
MethodType methodType = MethodType.methodType(method.getReturnType(), argTypes);
try{
MethodHandle methodHandle = MethodHandles.lookup().findVirtual(instance.getClass(), method.getName(), methodType);
cachedMethodHandles.put(methodKeyBuilder.toString(), methodHandle);
}
catch(Exception e){
e.printStackTrace();
}
}
}
/* (non-Javadoc)
* @see com.bluedavy.rpc.ServerHandler#handleRequest(com.bluedavy.rpc.RequestWrapper)
*/
@Override
public ResponseWrapper handleRequest(final RequestWrapper request){
ResponseWrapper responseWrapper = new ResponseWrapper();
responseWrapper.setRequestId(request.getId());
responseWrapper.setDataType(request.getDataType());
String targetInstanceName = request.getTargetInstanceName();
String methodName = request.getMethodName();
String[] argTypes = request.getArgTypes();
List<Object> requestObjects = null;
MethodHandle method = null;
try{
Object processor = processors.get(targetInstanceName);
requestObjects = new ArrayList<Object>(argTypes.length+1);
requestObjects.add(processor);
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]);
}
String key = methodKeyBuilder.toString();
method = cachedMethodHandles.get(key);
Object[] tmprequestObjects = request.getRequestObjects();
for (int i = 0; i < tmprequestObjects.length; i++) {
requestObjects.add(Coders.getDecoder(String.valueOf(request.getDataType())).decode((byte[])tmprequestObjects[i]));
}
}
else {
MethodType methodType = MethodType.methodType(Object.class, new Class<?>[]{});
method = MethodHandles.lookup().findVirtual(processor.getClass(), methodName, methodType);
}
responseWrapper.setResponse(method.invokeWithArguments(requestObjects));
}
catch(Throwable e){
responseWrapper.setException(e);
}
return responseWrapper;
}
}