JavaFunctionRpcWrapper.java
package eu.javaexperience.rpc.function;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Arrays;
import eu.javaexperience.reflect.NotatedCaster;
import eu.javaexperience.rpc.RpcCastTools;
import eu.javaexperience.rpc.RpcFunction;
import eu.javaexperience.rpc.RpcRequest;
//TODO make abstract parent for this and JavaAsIsFunctionWrapper
public class JavaFunctionRpcWrapper<C extends RpcRequest> implements RpcFunction<C, RpcFunctionParameter>
{
protected Method javaMethod;
protected String name;
protected RpcFunctionParameter returningType;
protected RpcFunctionParameter[] params;
public static JavaFunctionRpcWrapper<RpcRequest> wrapJavaFunction(Method m)
{
JavaFunctionRpcWrapper ret = new JavaFunctionRpcWrapper<>();
ret.javaMethod = m;
ret.javaMethod.setAccessible(true);
ret.name = m.getName();
ret.returningType = createByType(m.getGenericReturnType());
Type[] params = m.getGenericParameterTypes();
ret.params = new RpcFunctionParameter[params.length-1];
for(int i=1;i<params.length;++i)
{
ret.params[i-1] = createByType(params[i]);
}
return ret;
}
@Override
public String getMethodName()
{
return name;
}
@Override
public RpcFunctionParameter[] getParameterClasses()
{
return params;
}
@Override
public RpcFunctionParameter getReturningClass()
{
return returningType;
}
public Method getJavaMethod()
{
return javaMethod;
}
protected Object[] assembleJavaFunctionParameters(C ctx, Object thisContext, String functionName, Object... params)
{
Object[] cll = new Object[params.length+1];
cll[0] = ctx;
for(int i=0;i<params.length;++i)
{
cll[i+1] = params[i];
}
return cll;
}
@Override
public Object call(C ctx, Object thisContext, String functionName, Object... params) throws Throwable
{
Object[] cll = assembleJavaFunctionParameters(ctx, thisContext, functionName, params);
try
{
return javaMethod.invoke(thisContext, cll);
}
catch(InvocationTargetException ex)
{
if(ex.getCause() instanceof Throwable)
{
throw ex.getCause();
}
throw ex;
}
}
public static RpcFunctionParameter createByType(Type type)
{
Class<?> cls = RpcCastTools.extractClass(type);
if(void.class == cls || Void.class == cls)
{
return new RpcFunctionParameter(new NotatedCaster()
{
@Override
public Object cast(Object in)
{
return null;
}
@Override
public String getTypeShortName()
{
return "void";
}
@Override
public String getTypeFullQualifiedName()
{
return "void";
}
});
}
NotatedCaster c = RpcCastTools.tryCreateCaster(type);
if(null != c)
{
return new RpcFunctionParameter(c);
}
if(null == cls)
{
throw new RuntimeException("No suitable automatic caster for type: "+type);
}
return new RpcFunctionParameter(RpcCastTools.getDirectCaster(cls));
}
public static void teszt(RpcRequest req, int[] values)
{
System.out.println("Values: "+Arrays.toString((int[])values));
}
public static void main(String[] args) throws Throwable
{
Method m = JavaFunctionRpcWrapper.class.getMethod("teszt", RpcRequest.class, int[].class);
JavaFunctionRpcWrapper func = wrapJavaFunction(m);
func.call(null, null, "", new int[]{10,20});
//System.out.println(m.getReturnType());
}
}