package com.kurento.tool.rom.server;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import com.kurento.kmf.jsonrpcconnector.Props;
import com.kurento.tool.rom.RemoteClass;
import com.kurento.tool.rom.transport.serialization.ParamsFlattener;
public class RomServer {
private final RemoteObjectManager manager = new RemoteObjectManager();
private static ParamsFlattener FLATTENER = ParamsFlattener.getInstance();
private final String packageName;
private final String classSuffix;
public RomServer(String packageName, String classSuffix) {
this.packageName = packageName;
this.classSuffix = classSuffix;
}
public String create(String remoteClassType, Props constructorParams) {
try {
Class<?> clazz = Class.forName(packageName + "." + remoteClassType
+ classSuffix);
if (clazz.getAnnotation(RemoteClass.class) == null) {
throw new ProtocolException(
"Remote classes must be annotated with @RemoteClass");
}
Constructor<?> constructor = clazz.getConstructors()[0];
Object[] unflattenedConstParams = FLATTENER.unflattenParams(
constructor.getParameterAnnotations(),
constructor.getGenericParameterTypes(), constructorParams,
manager);
Object object = constructor.newInstance(unflattenedConstParams);
return manager.putObject(object);
} catch (Exception e) {
// TODO Improve exception reporting
throw new ProtocolException(
"Exception while creating an object with remoteClass='"
+ remoteClassType + "' and params="
+ constructorParams, e);
}
}
@SuppressWarnings("unchecked")
public <E> E invoke(String objectRef, String methodName, Props params,
Class<E> clazz) {
return (E) invoke(objectRef, methodName, params, (Type) clazz);
}
public Object invoke(String objectRef, String methodName, Props params,
Type type) {
Object remoteObject = manager.getObject(objectRef);
if (remoteObject == null) {
throw new MediaServerException("No object found with reference "
+ objectRef);
}
Class<?> remoteObjClass = remoteObject.getClass();
try {
Method method = getMethod(remoteObjClass, methodName);
Object[] unflattenParams = FLATTENER.unflattenParams(
method.getParameterAnnotations(),
method.getGenericParameterTypes(), params, manager);
Object result = method.invoke(remoteObject, unflattenParams);
return FLATTENER.flattenResult(result, manager);
} catch (Exception e) {
// TODO Improve exception reporting
throw new ProtocolException(
"Invocation exception of object with remoteClass='"
+ remoteObjClass.getSimpleName() + "', method="
+ methodName + " and params=" + params, e);
}
}
private Method getMethod(Class<?> remoteObjClass, String methodName) {
for (Method method : remoteObjClass.getMethods()) {
if (method.getName().equals(methodName)) {
return method;
}
}
throw new ProtocolException("Method '" + methodName
+ "' not found in class '"
+ remoteObjClass.getClass().getSimpleName() + "'");
}
public void release(String objectRef) {
this.manager.releaseObject(objectRef);
}
}