package fr.lteconsulting.hexa.revrpc.server; import java.lang.reflect.Field; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.HashMap; public class CallSerializer { public interface SerializedCallReceiver { void newCall( Class<?> interfaceClass, JSONObject obj ); } public CallSerializer( SerializedCallReceiver callReceiver ) { this.callReceiver = callReceiver; } private SerializedCallReceiver callReceiver; HashMap<Class<?>, Object> broadcastProxies = new HashMap<Class<?>, Object>(); public <T> T makeProxy( Class<T> implementedInterface, SerializedCallReceiver callback ) { SerializerInvocationHandler handler = new SerializerInvocationHandler( implementedInterface, callback ); @SuppressWarnings( "unchecked" ) T proxy = (T) Proxy.newProxyInstance( implementedInterface.getClassLoader(), new Class<?>[] { implementedInterface }, handler ); return proxy; } public <T> T queryBroadcastInterface( Class<T> implementedInterface ) { @SuppressWarnings( "unchecked" ) T proxy = (T) broadcastProxies.get( implementedInterface ); if( proxy != null ) return proxy; proxy = makeProxy( implementedInterface, callReceiver ); broadcastProxies.put( implementedInterface, proxy ); return proxy; } class SerializerInvocationHandler implements InvocationHandler { private Class<?> proxiedClass = null; private SerializedCallReceiver callback = null; public SerializerInvocationHandler( Class<?> proxiedClass, SerializedCallReceiver callback ) { this.proxiedClass = proxiedClass; this.callback = callback; } public Object invoke( Object proxy, Method method, Object[] args ) throws Throwable { JSONObject json = new JSONObject(); json.put( "method", (String) method.getName() ); JSONArray jsonArgs = new JSONArray(); for( int i = 0; i < args.length; i++ ) { JSONObject jsonArg = new JSONObject(); jsonArg.put( "type", (String) args[i].getClass().getCanonicalName() ); Object jsonArgValue = serializeToJSON( args[i] ); jsonArg.put( "value", jsonArgValue ); jsonArgs.set( i, jsonArg ); } json.put( "args", jsonArgs ); // emit the call callback.newCall( proxiedClass, json ); return null; } } private Object serializeToJSON( Object obj ) { if( obj instanceof String ) return (String) obj; if( obj instanceof Boolean ) return (Boolean) obj; if( obj instanceof Integer ) return (Integer) obj; if( obj.getClass().isEnum() ) { Object values[] = obj.getClass().getEnumConstants(); for( int e = 0; e < values.length; e++ ) { if( obj == values[e] ) { // we found our enum Method nameMethod = null; try { nameMethod = obj.getClass().getMethod( "name" ); } catch( SecurityException e1 ) { // TODO Auto-generated catch block e1.printStackTrace(); } catch( NoSuchMethodException e1 ) { // TODO Auto-generated catch block e1.printStackTrace(); } String enumName = null; try { enumName = (String) nameMethod.invoke( obj ); } catch( IllegalArgumentException e1 ) { // TODO Auto-generated catch block e1.printStackTrace(); } catch( IllegalAccessException e1 ) { // TODO Auto-generated catch block e1.printStackTrace(); } catch( InvocationTargetException e1 ) { // TODO Auto-generated catch block e1.printStackTrace(); } return enumName; } } } JSONObject json = new JSONObject(); Field fields[] = obj.getClass().getFields(); for( int i = 0; i < fields.length; i++ ) { Field field = fields[i]; // TODO : not serialize field if final or transient Object fieldValue = null; try { fieldValue = field.get( obj ); } catch( IllegalArgumentException e ) { e.printStackTrace(); } catch( IllegalAccessException e ) { e.printStackTrace(); } json.put( field.getName(), serializeToJSON( fieldValue ) ); } return json; } }