| InterceptorInvoker.java |
package org.mockejb.interceptor;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import net.sf.cglib.reflect.FastClass;
import net.sf.cglib.reflect.FastMethod;
/**
* Requests the interceptors from the AspectSystem and
* initiates the call to the interceptor chain.
* Allows to setup the custom context (properties) that is passed down to interceptors.
* Clients can reuse the same object of this class for all method
* calls (provided that that the custom context is the same).
*
* @author Alexander Ananiev
*/
public class InterceptorInvoker implements Serializable {
private transient AspectSystem aspectSystem = AspectSystemFactory.getAspectSystem();
private Map context = new HashMap();
/**
* Calls AspectSystem to find the interceptors for the given invokedMethod and
* targetMethod, creates the
* invocationContext and proceeds to calling the first interceptor.
* @param proxyObj dynamic proxy or the object enhanced by CGLIB.
* @param proxyMethod method invoked by the client on the proxy. Normally, this is an interface method
* (the declaring class is the interface).
* @param targetObj object to call, e.g., EJB implementation object
* @param targetMethod method to call on the target object, e.g., method of the EJB implementation clsess
* @param paramVals method parameters
*
* @return return value
*/
public Object invoke( Object proxyObj, Method proxyMethod,
Object targetObj, Method targetMethod, Object[] paramVals ) throws Exception {
List interceptorList =
aspectSystem.findInterceptors( proxyMethod, targetMethod );
// add the method calling interceptor
interceptorList.add( new CglibMethodInvoker( ) );
InvocationContext invocationContext = new InvocationContext( interceptorList, proxyObj,
proxyMethod, targetObj, targetMethod, paramVals, context );
invocationContext.proceed();
return invocationContext.getReturnObject();
}
/**
* Sets the custom context.
* Custome context is the is a piece of data made available
* to all interceptors
* @param key key for this context's data
* @param data context data
*/
public void setContext( String key, Object data ){
context.put( key, data );
}
/**
* Returns the context associated with the provided key
* or null if the key is not found.
* @param key context key
* @return context data
*/
public Object getContext( String key ) {
return context.get( key );
}
/**
* Calls the object's method using Cglib.
*/
static public class CglibMethodInvoker implements Interceptor {
public void intercept( InvocationContext invocationContext ) throws Exception {
try { // this try is to convert Throwable to Exception
Method targetMethod = invocationContext.getTargetMethod();
FastClass fastClass = FastClass.create( targetMethod.getDeclaringClass() );
FastMethod fastMethod = fastClass.getMethod( targetMethod );
Object returnObj;
try {
returnObj = fastMethod.invoke( invocationContext.getTargetObject(),
invocationContext.getParamVals());
}
//We need to re-throw the cause of the exception,
// we don't want to show that the reflection is used.
catch( InvocationTargetException ite ){
throw ite.getTargetException();
}
invocationContext.setReturnObject( returnObj );
}
// convert throwable to Error or Exception
// this allows us not to use throwable as part of a method signature
catch( Throwable throwable) {
if ( throwable instanceof Error ) {
throw (Error)throwable;
}
else if ( throwable instanceof Exception ){
throw (Exception)throwable;
}
}
}
} // end of CglibMethodInvoker
}