com.googlecode.gwt.test.rpc.RemoteServiceCreateHandler Maven / Gradle / Ivy
package com.googlecode.gwt.test.rpc;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
import com.googlecode.gwt.test.GwtCreateHandler;
import com.googlecode.gwt.test.exceptions.GwtTestRpcException;
import com.googlecode.gwt.test.internal.GwtClassPool;
import com.googlecode.gwt.test.utils.GwtReflectionUtils;
import javassist.CtClass;
import javassist.bytecode.annotation.AnnotationImpl;
import javassist.bytecode.annotation.StringMemberValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Proxy;
/**
*
* The {@link GwtCreateHandler} class used to create {@link RemoteService} sub-interface instances.
* It returns an asynchrone proxy of the service and handles the simulation of GWT-RPC serialization
* through a {@link GwtRpcInvocationHandler} and the exception management through a
* {@link GwtRpcExceptionHandler}.
*
*
*
* Before delegating the remote service object instantiation to the abstract
* {@link RemoteServiceCreateHandler#findService(Class, String)} method, this class ensure that a
* corresponding async interface is available for the RemoteService subinterface to create.
*
*
* @author Bertrand Paquet
* @author Gael Lazzari
*/
public abstract class RemoteServiceCreateHandler implements GwtCreateHandler {
private class DefaultGwtRpcExceptionHandler implements GwtRpcExceptionHandler {
public void handle(Throwable t, AsyncCallback callback) {
callback.onFailure(t);
}
}
private class DefaultGwtRpcSerializerHandler implements GwtRpcSerializerHandler {
public T serializeUnserialize(T o) throws Exception {
return DeepCopy.copy(o);
}
}
private static final Logger logger = LoggerFactory.getLogger(RemoteServiceCreateHandler.class);
private final GwtRpcExceptionHandler exceptionHandler;
private final GwtRpcSerializerHandler serializerHander;
public RemoteServiceCreateHandler() {
exceptionHandler = getExceptionHandler();
serializerHander = getSerializerHandler();
}
public Object create(Class classLiteral) throws Exception {
if (!RemoteService.class.isAssignableFrom(classLiteral)) {
return null;
}
String className = classLiteral.getName();
logger.debug("Try to create Remote service class " + className);
String asyncName = className + "Async";
String relativePath = getRemoveServiceRelativePath(classLiteral);
Class asyncClazz = GwtReflectionUtils.getClass(asyncName);
if (asyncClazz == null) {
throw new GwtTestRpcException("Remote serivce Async class not found : " + asyncName);
}
logger.debug("Searching remote service implementing " + className);
// try to find
Object service = findService(classLiteral, relativePath);
if (service == null) {
return null;
}
GwtRpcInvocationHandler handler = new GwtRpcInvocationHandler(asyncClazz, service,
exceptionHandler, serializerHander);
return Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{asyncClazz}, handler);
}
/**
* Method which actually is responsible for getting the {@link RemoteService} sub-interface
* implementation.
*
* @param remoteServiceClass {@link RemoteService} sub-interface to get an implementation.
* @param remoteServiceRelativePath the associated relative path, which is provided in
* {@link RemoteServiceRelativePath} annotation.
* @return The corresponding remote service implementation.
*/
protected abstract Object findService(Class remoteServiceClass,
String remoteServiceRelativePath);
/**
* Specify the handler to use to handle GWT-RPC errors.
*
* @return The handler to use to handle GWT-RPC errors.
*/
protected GwtRpcExceptionHandler getExceptionHandler() {
return new DefaultGwtRpcExceptionHandler();
}
/**
* Specify the handler to use to simulate the GWT-RPC serialization
*
* @return The handler to use to simulate the GWT-RPC serialization.
*/
protected GwtRpcSerializerHandler getSerializerHandler() {
return new DefaultGwtRpcSerializerHandler();
}
private String getRemoveServiceRelativePath(Class clazz) {
CtClass ctClass = GwtClassPool.getCtClass((clazz));
Object[] annotations = ctClass.getAvailableAnnotations();
for (Object o : annotations) {
if (Proxy.isProxyClass(o.getClass())) {
AnnotationImpl annotation = (AnnotationImpl) Proxy.getInvocationHandler(o);
if (annotation.getTypeName().equals(RemoteServiceRelativePath.class.getName())) {
return ((StringMemberValue) annotation.getAnnotation().getMemberValue("value")).getValue();
}
}
}
throw new GwtTestRpcException("Cannot find the '@"
+ RemoteServiceRelativePath.class.getSimpleName()
+ "' annotation on RemoteService interface '" + clazz.getName() + "'");
}
}