package org.limewire.util;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* A generic class that allows you to mimic an interface.
* See: http://www.coconut-palm-software.com/the_visual_editor/?p=25
* for more information
*/
public class DuckType implements InvocationHandler {
private final Object object;
private final Class objectClass;
private DuckType(Object object) {
this.object = object;
this.objectClass = object.getClass();
}
@SuppressWarnings("unchecked")
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Method realMethod = objectClass.getMethod(method.getName(), method.getParameterTypes());
return realMethod.invoke(object, args);
}
/**
* Returns an object that implements the given interface and
* delegates all calls (through reflection) to the given object.
*
* @param interfaceToImplement The interface that must be implemented
* @param object The object calls will delegate to
* @return A new object that implements the interface.
*/
public static Object implement(Class interfaceToImplement, Object object) {
if(!instanceOf(interfaceToImplement, object))
throw new IllegalArgumentException("object: " + object + " does not have all the methods of: " + interfaceToImplement);
return Proxy.newProxyInstance(interfaceToImplement.getClassLoader(),
new Class[] {interfaceToImplement}, new DuckType(object));
}
/**
* Indicates if object is a (DuckType) instance of intrface. That is,
* is every method in intrface present on object.
*
* @param intrface The interface to implement
* @param object The object to test
* @return true if every method in intrface is present on object. false otherwise
*/
@SuppressWarnings("unchecked")
public static boolean instanceOf(Class intrface, Object object) {
final Method[] methods = intrface.getMethods();
Class candclass=object.getClass();
for (int methodidx = 0; methodidx < methods.length; methodidx++) {
Method method=methods[methodidx];
try {
candclass.getMethod(method.getName(), method.getParameterTypes());
} catch (NoSuchMethodException e) {
return false;
}
}
return true;
}
}