package org.alfresco.traitextender;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.alfresco.traitextender.AJExtender.ExtensionBypass;
import org.alfresco.util.ParameterCheck;
/**
* Java {@link Proxy} {@link InvocationHandler} to be used in conjuction with
* asprctJ extended traits.
* Method calls will be delegated to a given {@link Extensible} object method
* having the same signature within an {@link ExtensionBypass} context.
*
* @author Bogdan Horje
*/
public class AJProxyTrait implements InvocationHandler
{
/**
* {@link Trait} {@link Proxy} factory method.
*
* @param extensible the {@link Extensible} object that defines the given
* {@link Trait}
* @param traitAPI the trait interface part that the given
* {@link Extensible} object defines
* @return a {@link Proxy} object for the given trait API interface with an
* {@link AJProxyTrait} attached. All method calls performed on the
* returned proxy will be delegated to a given {@link Extensible}
* object method having the same signature within an
* {@link ExtensionBypass} context.
*/
@SuppressWarnings("unchecked")
public static M create(Object extensibleInterface, Class traitAPI)
{
return (M) Proxy.newProxyInstance(AJProxyTrait.class.getClassLoader(),
new Class[] { traitAPI },
new AJProxyTrait(extensibleInterface));
}
private Object extensibleInterface;
private AJProxyTrait(Object extensibleInterface)
{
ParameterCheck.mandatory("extensible",
extensibleInterface);
this.extensibleInterface = extensibleInterface;
}
@Override
public Object invoke(Object proxy, Method method, final Object[] args) throws Throwable
{
final Method traitMethod = extensibleInterface.getClass().getMethod(method.getName(),
method.getParameterTypes());
if (AJExtender.isLocalProceeder(method))
{
return AJExtender.localProceed(args);
}
else
{
Class>[] exTypes = traitMethod.getExceptionTypes();
return AJExtender.run(new AJExtender.ExtensionBypass