package com.pccw.hessian.support.client;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.Arrays;
import com.caucho.hessian.client.HessianProxyFactory;
import com.caucho.hessian.client.HessianRuntimeException;
import com.caucho.hessian.client.HessianHttpProxyFactory.HessianHttpProxy;
import com.pccw.hessian.support.cache.CacheHandler;
import com.pccw.hessian.support.cache.CachePolicy;
import com.pccw.hessian.support.cache.OptModel;
/**
* Hessian cache,asynchronous,http Proxy
* @author guxuede
*
*/
public class HessianCAHProxy extends HessianHttpProxy{
//private static final Logger log = Logger.getLogger(HessianCAHProxy.class.getName());
private CacheHandler cacheHandler;
private ExceptionHandler exceptionHandler;
public HessianCAHProxy(HessianProxyFactory factory, URL url,CacheHandler cacheHandler,ExceptionHandler exceptionHandler,RemoteProxy remoteURL) {
super(factory, url);
this.cacheHandler=cacheHandler;
this.exceptionHandler=exceptionHandler;
if(remoteURL!=null){
remoteURL.setProxy(this);
}
}
@SuppressWarnings("unchecked")
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
/**
* =========================================异步任务块
*/
TaskExecuteListener<Object,Throwable> taskExecuteListener=null;
if(args!=null && args.length > 0 && args[args.length-1] instanceof TaskExecuteListener){//检测该方法是否为异步方法,检测的依据是改方法的参数列表中最后一个参数类型是TaskExecuteListener
taskExecuteListener=(TaskExecuteListener<Object,Throwable>) args[args.length-1];
args=SupportUtils.copyOfRange(args, 0, args.length-1);
method=getNoAsynMethod(method);//将方法和参数都换成非异步的方法和参数
taskExecuteListener.onPerExecute(method, args);
}
/**
* =========================================缓存块(读)
*/
OptModel model=(method.getAnnotation(CachePolicy.class)==null || cacheHandler==null)?OptModel.NONE:method.getAnnotation(CachePolicy.class).model();
if(model.equals(OptModel.READ) || (model.equals(OptModel.BOTH) && cacheHandler.ifReturnFromCahce(method, args))){//如果需要从缓存中获取,则直接从缓存中取
Object result=cacheHandler.returnFromCahce(method, args);
if(taskExecuteListener!=null){
taskExecuteListener.onExecuteSuccess(method, args, result);
taskExecuteListener.onFinally(method, args,result);
}
return result;
}
if(taskExecuteListener!=null){//如果需要向远程获取数据且发现为异步任务,那么启动异步方法执行任务,本方法直接返回null
invokeAsyn(proxy, method, args,model,cacheHandler,taskExecuteListener);
return null;
}else{//直接阻塞式向远程服务端请求数据
try {
Object result=super.invoke(proxy, method, args);
if(model.equals(OptModel.WRITE) || model.equals(OptModel.BOTH)){
cacheHandler.onExecuteSuccess(method, args,result);
}
return result;
} catch (Throwable e) {
throw exceptionHandler.parseException(e);
}
}
}
@SuppressWarnings("unchecked")
private void invokeAsyn(final Object proxy, final Method method, final Object[] args,final OptModel model,final CacheHandler cacheHandler,final TaskExecuteListener<Object,Throwable> taskExecuteListener){
((HessianCAHProxyFactory)_factory).getAsynTaskExecuter().execute(new HessianAsynTask<Object,Throwable>() {
@Override
public Object doInBackground() throws Throwable {
return HessianCAHProxy.super.invoke(proxy, method, args);
}
@Override
public void onExceptionOccured(Throwable exception) {
exception=exceptionHandler.parseException(exception);
taskExecuteListener.onExceptionOccured(method, args, exception);
}
@Override
public void onExecuteSuccess(Object result) {
taskExecuteListener.onExecuteSuccess(method, args, result);
if(model.equals(OptModel.WRITE) || model.equals(OptModel.BOTH)){
cacheHandler.onExecuteSuccess(method, args, result);
}
}
@Override
public void onFinally(Object result) {
taskExecuteListener.onFinally(method, args, result);
}
});
}
/**
* 得到异步方法的非异步方法。
* 比如: login(String username,String password,TaskExecuteListener listener)
* 一定存在:login(String username,String password);
* 否则将抛出NoSuchMethodException
* @param proxy
* @param method
* @return
* @throws NoSuchMethodException
* @throws SecurityException
*/
private Method getNoAsynMethod(Method method){
Class<?>[] src=method.getParameterTypes();
try {
return method.getDeclaringClass().getDeclaredMethod(method.getName(), SupportUtils.copyOfRange(src,0,src.length-1));
} catch (Exception e) {
throw new HessianRuntimeException(e);
}
}
public static class RemoteProxy{
private HessianCAHProxy proxy;
public HessianCAHProxy getProxy() {
return proxy;
}
public void setProxy(HessianCAHProxy proxy) {
this.proxy = proxy;
}
}
}