public Object invoke(final Object obj, final Method thisMethod, final Method proceed, final Object[] args)
throws Throwable
{
if (Thread.currentThread().isInterrupted())
{
throw new ContainerException("Thread.interrupt() requested.");
}
Object result = ClassLoaders.executeIn(delegateLoader, new Callable<Object>()
{
@Override
public Object call() throws Exception
{
try
{
if (thisMethod.getDeclaringClass().getName().equals(ForgeProxy.class.getName()))
{
if (thisMethod.getName().equals("getDelegate"))
return ClassLoaderAdapterCallback.this.getDelegate();
if (thisMethod.getName().equals("getHandler"))
return ClassLoaderAdapterCallback.this.getHandler();
}
}
catch (final Exception e)
{
}
final Method delegateMethod = getDelegateMethod(thisMethod);
final List<Object> parameterValues = enhanceParameterValues(args, delegateMethod);
AccessibleObject.setAccessible(new AccessibleObject[] { delegateMethod }, true);
try
{
final Object[] parameterValueArray = parameterValues.toArray();
final Object result = delegateMethod.invoke(delegate, parameterValueArray);
return enhanceResult(thisMethod, result);
}
catch (final InvocationTargetException e)
{
if (e.getCause() instanceof Exception)
throw enhanceException(delegateMethod, (Exception) e.getCause());
throw enhanceException(delegateMethod, e);
}
}
private Method getDelegateMethod(final Method proxy) throws ClassNotFoundException, NoSuchMethodException
{
Method delegateMethod = null;
try
{
final List<Class<?>> parameterTypes = translateParameterTypes(proxy);
delegateMethod = delegate.getClass().getMethod(proxy.getName(),
parameterTypes.toArray(new Class<?>[parameterTypes.size()]));
}
catch (final ClassNotFoundException e)
{
method: for (final Method m : delegate.getClass().getMethods())
{
final String methodName = proxy.getName();
final String delegateMethodName = m.getName();
if (methodName.equals(delegateMethodName))
{
final Class<?>[] methodParameterTypes = proxy.getParameterTypes();
final Class<?>[] delegateParameterTypes = m.getParameterTypes();
if (methodParameterTypes.length == delegateParameterTypes.length)
{
for (int i = 0; i < methodParameterTypes.length; i++)
{
final Class<?> methodType = methodParameterTypes[i];
final Class<?> delegateType = delegateParameterTypes[i];
if (!methodType.getName().equals(delegateType.getName()))
{
continue method;
}
}
delegateMethod = m;
break;
}
}
}
if (delegateMethod == null)
throw e;
}
return delegateMethod;
}
});
if (Thread.currentThread().isInterrupted())
{
throw new ContainerException("Thread.interrupt() requested.");
}
return result;
}