001: package org.mockejb.interceptor;
002:
003: import java.io.Serializable;
004:
005: import java.lang.reflect.InvocationTargetException;
006: import java.lang.reflect.Method;
007: import java.util.*;
008:
009: import net.sf.cglib.reflect.FastClass;
010: import net.sf.cglib.reflect.FastMethod;
011:
012: /**
013: * Requests the interceptors from the AspectSystem and
014: * initiates the call to the interceptor chain.
015: * Allows to setup the custom context (properties) that is passed down to interceptors.
016: * Clients can reuse the same object of this class for all method
017: * calls (provided that that the custom context is the same).
018: *
019: * @author Alexander Ananiev
020: */
021: public class InterceptorInvoker implements Serializable {
022:
023: private transient AspectSystem aspectSystem = AspectSystemFactory
024: .getAspectSystem();
025:
026: private Map context = new HashMap();
027:
028: /**
029: * Calls AspectSystem to find the interceptors for the given invokedMethod and
030: * targetMethod, creates the
031: * invocationContext and proceeds to calling the first interceptor.
032: * @param proxyObj dynamic proxy or the object enhanced by CGLIB.
033: * @param proxyMethod method invoked by the client on the proxy. Normally, this is an interface method
034: * (the declaring class is the interface).
035: * @param targetObj object to call, e.g., EJB implementation object
036: * @param targetMethod method to call on the target object, e.g., method of the EJB implementation clsess
037: * @param paramVals method parameters
038: *
039: * @return return value
040: */
041: public Object invoke(Object proxyObj, Method proxyMethod,
042: Object targetObj, Method targetMethod, Object[] paramVals)
043: throws Exception {
044:
045: List interceptorList = aspectSystem.findInterceptors(
046: proxyMethod, targetMethod);
047:
048: // add the method calling interceptor
049: interceptorList.add(new CglibMethodInvoker());
050:
051: InvocationContext invocationContext = new InvocationContext(
052: interceptorList, proxyObj, proxyMethod, targetObj,
053: targetMethod, paramVals, context);
054:
055: invocationContext.proceed();
056:
057: return invocationContext.getReturnObject();
058: }
059:
060: /**
061: * Sets the custom context.
062: * Custome context is the is a piece of data made available
063: * to all interceptors
064: * @param key key for this context's data
065: * @param data context data
066: */
067: public void setContext(String key, Object data) {
068: context.put(key, data);
069: }
070:
071: /**
072: * Returns the context associated with the provided key
073: * or null if the key is not found.
074: * @param key context key
075: * @return context data
076: */
077: public Object getContext(String key) {
078: return context.get(key);
079: }
080:
081: /**
082: * Calls the object's method using Cglib.
083: */
084: static public class CglibMethodInvoker implements Interceptor {
085:
086: public void intercept(InvocationContext invocationContext)
087: throws Exception {
088:
089: try { // this try is to convert Throwable to Exception
090: Method targetMethod = invocationContext
091: .getTargetMethod();
092: FastClass fastClass = FastClass.create(targetMethod
093: .getDeclaringClass());
094: FastMethod fastMethod = fastClass
095: .getMethod(targetMethod);
096:
097: Object returnObj;
098:
099: try {
100: returnObj = fastMethod.invoke(invocationContext
101: .getTargetObject(), invocationContext
102: .getParamVals());
103: }
104: //We need to re-throw the cause of the exception,
105: // we don't want to show that the reflection is used.
106: catch (InvocationTargetException ite) {
107: throw ite.getTargetException();
108: }
109:
110: invocationContext.setReturnObject(returnObj);
111: }
112: // convert throwable to Error or Exception
113: // this allows us not to use throwable as part of a method signature
114:
115: catch (Throwable throwable) {
116: if (throwable instanceof Error) {
117: throw (Error) throwable;
118: } else if (throwable instanceof Exception) {
119: throw (Exception) throwable;
120: }
121: }
122: }
123: } // end of CglibMethodInvoker
124:
125: }
|