package code.google.nfs.rpc.client;
/**
* nfs-rpc
* Apache License
*
* http://code.google.com/p/nfs-rpc (c) 2011
*/
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.net.InetSocketAddress;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Random;
/**
* Abstract Client Invocation Handler,help for client proxy
*
* @author <a href="mailto:bluedavy@gmail.com">bluedavy</a>
*/
public abstract class AbstractClientInvocationHandler implements InvocationHandler {
private List<InetSocketAddress> servers;
private int clientNums;
private int connectTimeout;
private String targetInstanceName;
private int codecType;
private int protocolType;
// per method timeout,some special method use methodName.toLowerCase to set timeout,other use *
private Map<String, Integer> methodTimeouts;
public AbstractClientInvocationHandler(List<InetSocketAddress> servers,int clientNums,int connectTimeout,
String targetInstanceName,Map<String, Integer> methodTimeouts,
int codecType,int protocolType){
this.servers = Collections.unmodifiableList(servers);
this.clientNums = clientNums;
this.connectTimeout = connectTimeout;
this.methodTimeouts = methodTimeouts;
this.targetInstanceName = targetInstanceName;
this.codecType = codecType;
this.protocolType = protocolType;
}
public void updateServers(List<InetSocketAddress> servers){
this.servers = Collections.unmodifiableList(servers);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
InetSocketAddress server = null;
if(servers.size() == 1){
server = servers.get(0);
}
else{
// random is not thread-safe,so...
Random random = new Random();
server = servers.get(random.nextInt(servers.size()));
}
Client client = getClientFactory().get(server.getAddress().getHostAddress(), server.getPort(), connectTimeout, clientNums);
String methodName = method.getName();
String[] argTypes = createParamSignature(method.getParameterTypes());
int timeout = 0;
if(methodTimeouts.containsKey(methodName.toLowerCase())){
timeout = methodTimeouts.get(methodName);
}
else{
timeout = methodTimeouts.get("*");
}
return client.invokeSync(targetInstanceName, methodName, argTypes, args, timeout, codecType, protocolType);
}
private String[] createParamSignature(Class<?>[] argTypes) {
if (argTypes == null || argTypes.length == 0) {
return new String[] {};
}
String[] paramSig = new String[argTypes.length];
for (int x = 0; x < argTypes.length; x++) {
paramSig[x] = argTypes[x].getName();
}
return paramSig;
}
public abstract ClientFactory getClientFactory();
}