package org.oddjob.framework; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; /** * Default invocation handler for Proxies for wrapped components. * * @author rob * */ public class DefaultInvocationHandler implements WrapperInvocationHandler, Serializable { private static final long serialVersionUID = 2012012200L; /** * Map of methods to the object that it will be invoked on. */ private transient Map<Method, Object> methods; private ComponentWrapper wrapper; private Class<?>[] wrappingInterfaces; private Object wrapped; private Class<?>[] wrappedInterfaces; /** * Initialise the invocation handler. * * @param wrapper The wrapper. Handles invocations for wrapping * interfaces. * @param wrappingInterfaces The wrapping interfaces. * @param wrapped The component. * @param wrappedInterfaces The component interfaces. */ public void initialise(ComponentWrapper wrapper, Class<?>[] wrappingInterfaces, Object wrapped, Class<?>[] wrappedInterfaces) { this.wrapper = wrapper; this.wrappingInterfaces = wrappingInterfaces; this.wrapped = wrapped; this.wrappedInterfaces = wrappedInterfaces; initialiseMethods(); } private void initialiseMethods() { this.methods = new HashMap<Method, Object>(); { Class<?>[] interfaces = wrappedInterfaces; for (int i = 0; i < interfaces.length; ++i) { addMethods(interfaces[i], wrapped); } } { Class<?>[] interfaces = wrappingInterfaces; for (int i = 0; i < interfaces.length; ++i) { addMethods(interfaces[i], wrapper); } } } /** * Add a method and the object that is going to implement it. * * @param from * @param destination */ private void addMethods(Class<?> from, Object destination) { Method[] ms = from.getMethods(); for (int i = 0; i < ms.length; ++i) { methods.put(ms[i], destination); } } @Override public Object getWrappedComponent() { return wrapped; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object destination = methods.get(method); if (destination == null) { throw new IllegalStateException("Unknown method " + method + " for [" + wrapped + "]."); } return method.invoke(destination, args); } /** * Custom serialisation. */ private void writeObject(ObjectOutputStream s) throws IOException { s.defaultWriteObject(); } /** * Custom serialisation. */ private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { s.defaultReadObject(); initialiseMethods(); } }