package org.rzo.netty.ahessian.rpc.server;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.rzo.netty.ahessian.Constants;
import org.rzo.netty.ahessian.rpc.callback.ClientCallback;
import org.rzo.netty.ahessian.rpc.callback.ServerCallbackProxy;
import org.rzo.netty.ahessian.rpc.message.HessianRPCCallMessage;
import org.rzo.netty.ahessian.rpc.message.HessianRPCReplyMessage;
/**
* Wraps an object as a {@link Service}. Methods are invoked as soon as they are received.
* Invocation and return of result are executed within the netty worker thread. <br>
* This type of service is used for short running invocations.
* <br>
* Typical usage:
* <pre>
*
* // the object to be wrapped, implements MyServiceInterface
* Object myServiceObject;
*
* // the netty rpc service handler
* HessianRPCServiceHandler handler;
*
* Service myService = new ImmediateInvokeService(myServiceObject, MyServiceInterface.class);
*
* // Clients will access the service through the given name
* handler.addService("myServiceName", myService);
*
* </pre>
*/
public class ImmediateInvokeService extends HessianSkeleton implements Constants
{
/**
* Instantiates a new immediate invoke service.
*
* @param service the service object implementing apiClass
* @param apiClass the api of the service exposed to the client
* @param factory the netty handler
*/
public ImmediateInvokeService(Object service, Class apiClass, HessianRPCServiceHandler factory)
{
super(service, apiClass, factory);
}
/* (non-Javadoc)
* @see org.rzo.netty.ahessian.rpc.server.HessianSkeleton#messageReceived(org.rzo.netty.ahessian.rpc.HessianRPCCallMessage)
*/
@Override
public void messageReceived(HessianRPCCallMessage message)
{
ServiceSessionProvider.set(message.getSession());
invoke(message);
ServiceSessionProvider.remove();
}
/**
* Invokes the RPC call and sends back the result
*
* @param message the message
*/
void invoke(HessianRPCCallMessage message)
{
Object result = null;
Object fault = null;
try
{
Method method = getMethod(message);
Object[] args = message.getArgs();
if (args != null)
{
for (int i=0; i<args.length; i++)
{
if (args[i] instanceof ClientCallback)
{
ClientCallback cc = (ClientCallback) args[i];
ClassLoader cl = cc.getClass().getClassLoader();
Class clazz = cl.loadClass(cc.getCallbackClass());
List<Class> clazzes = new ArrayList();
while (clazz != null && (!clazz.equals(Object.class)))
{
clazzes.addAll(Arrays.asList(clazz.getInterfaces()));
clazz = clazz.getSuperclass();
}
args[i] = Proxy.newProxyInstance(cl, (Class[])clazzes.toArray(new Class[clazzes.size()]), new ServerCallbackProxy(_factory, message, (ClientCallback) args[i]));
}
}
}
result = method.invoke(_service, args);
}
catch (Throwable ex)
{
Constants.ahessianLogger.warn("", ex);
fault = ex;
}
HessianRPCReplyMessage reply = new HessianRPCReplyMessage(result, fault, message);
reply.setCompleted(true);
reply.setCallId((Long) message.getHeaders().get(CALL_ID_HEADER_KEY));
reply.setGroup((Integer) message.getHeaders().get(GROUP_HEADER_KEY));
writeResult(reply);
}
}