001: package com.mockrunner.struts;
002:
003: import java.lang.reflect.Method;
004: import java.util.Arrays;
005: import java.util.HashSet;
006: import java.util.Iterator;
007: import java.util.Set;
008:
009: import net.sf.cglib.proxy.Enhancer;
010: import net.sf.cglib.proxy.MethodInterceptor;
011: import net.sf.cglib.proxy.MethodProxy;
012:
013: import com.mockrunner.util.common.MethodUtil;
014:
015: /**
016: * Helper class to generate CGLib proxies. Not meant for application use.
017: */
018: public class DynamicMockProxyGenerator {
019: private Class proxiedClass;
020: private Object delegate;
021: private Class additionalInterface;
022: private Set methodsToIntercept;
023: private Set methodsToDuplicate;
024:
025: public DynamicMockProxyGenerator(Class proxiedClass,
026: Object delegate, Method[] methodsToIntercept,
027: Method[] methodsToDuplicate) {
028: this (proxiedClass, delegate, methodsToIntercept,
029: methodsToDuplicate, null);
030: }
031:
032: public DynamicMockProxyGenerator(Class proxiedClass,
033: Object delegate, Method[] methodsToIntercept,
034: Method[] methodsToDuplicate, Class additionalInterface) {
035: this .proxiedClass = proxiedClass;
036: this .delegate = delegate;
037: this .additionalInterface = additionalInterface;
038: this .methodsToIntercept = new HashSet();
039: this .methodsToIntercept.addAll(Arrays
040: .asList(methodsToIntercept));
041: this .methodsToDuplicate = new HashSet();
042: this .methodsToDuplicate.addAll(Arrays
043: .asList(methodsToDuplicate));
044: }
045:
046: public Object createProxy() {
047: Enhancer enhancer = new Enhancer();
048: enhancer.setSuperclass(proxiedClass);
049: if (null != additionalInterface) {
050: enhancer.setInterfaces(new Class[] { additionalInterface });
051: }
052: Method[] targetInterceptMethods = getActualTargetMethods(
053: delegate, methodsToIntercept);
054: Method[] targetDuplicateMethods = getActualTargetMethods(
055: delegate, methodsToDuplicate);
056: enhancer.setCallback(new DelegatingInterceptor(delegate,
057: targetInterceptMethods, targetDuplicateMethods));
058: return enhancer.create();
059: }
060:
061: private Method[] getActualTargetMethods(Object delegate,
062: Set providedMethods) {
063: Method[] methods = delegate.getClass().getMethods();
064: Set actualMethods = new HashSet();
065: Set tempProvidedMethods = new HashSet(providedMethods);
066: for (int ii = 0; ii < methods.length; ii++) {
067: findAndAddMethod(tempProvidedMethods, methods[ii],
068: actualMethods);
069: }
070: return (Method[]) actualMethods
071: .toArray(new Method[actualMethods.size()]);
072: }
073:
074: private void findAndAddMethod(Set providedMethods,
075: Method currentMethod, Set actualMethods) {
076: Iterator iterator = providedMethods.iterator();
077: while (iterator.hasNext()) {
078: Method currentMethodToIntercept = (Method) iterator.next();
079: if (MethodUtil.areMethodsEqual(currentMethod,
080: currentMethodToIntercept)) {
081: actualMethods.add(currentMethod);
082: iterator.remove();
083: return;
084: }
085: }
086: }
087:
088: private static class DelegatingInterceptor implements
089: MethodInterceptor {
090: private Object delegate;
091: private Method[] methodsToIntercept;
092: private Method[] methodsToDuplicate;
093:
094: public DelegatingInterceptor(Object delegate,
095: Method[] methodsToIntercept, Method[] methodsToDuplicate) {
096: this .delegate = delegate;
097: this .methodsToIntercept = methodsToIntercept;
098: this .methodsToDuplicate = methodsToDuplicate;
099: }
100:
101: public Object intercept(Object obj, Method method,
102: Object[] args, MethodProxy proxy) throws Throwable {
103: for (int ii = 0; ii < methodsToIntercept.length; ii++) {
104: if (MethodUtil.areMethodsEqual(method,
105: methodsToIntercept[ii])) {
106: return methodsToIntercept[ii]
107: .invoke(delegate, args);
108: }
109: }
110: for (int ii = 0; ii < methodsToDuplicate.length; ii++) {
111: if (MethodUtil.areMethodsEqual(method,
112: methodsToDuplicate[ii])) {
113: methodsToDuplicate[ii].invoke(delegate, args);
114: }
115: }
116: return proxy.invokeSuper(obj, args);
117: }
118: }
119: }
|