1 5 package org.easymock.classextension.internal; 6 7 import java.lang.reflect.Field ; 8 import java.lang.reflect.InvocationHandler ; 9 import java.lang.reflect.Method ; 10 import java.util.Arrays ; 11 import java.util.HashSet ; 12 import java.util.List ; 13 import java.util.Set ; 14 15 import net.sf.cglib.core.CollectionUtils; 16 import net.sf.cglib.core.VisibilityPredicate; 17 import net.sf.cglib.proxy.Callback; 18 import net.sf.cglib.proxy.Enhancer; 19 import net.sf.cglib.proxy.MethodInterceptor; 20 import net.sf.cglib.proxy.MethodProxy; 21 22 import org.easymock.internal.IProxyFactory; 23 import org.easymock.internal.ObjectMethodsFilter; 24 25 30 public class ClassProxyFactory implements IProxyFactory { 31 32 private Set mockedMethods; 33 34 41 public ClassProxyFactory(Method [] mockedMethods) { 42 this.mockedMethods = (mockedMethods == null ? null : new HashSet (Arrays 43 .asList(mockedMethods))); 44 } 45 46 public Object createProxy(Class toMock, final InvocationHandler handler) { 47 48 try { 55 updateMethod(handler, toMock.getMethod("equals", 56 new Class [] { Object .class })); 57 updateMethod(handler, toMock.getMethod("hashCode", new Class [0])); 58 updateMethod(handler, toMock.getMethod("toString", new Class [0])); 59 } catch (NoSuchMethodException e) { 60 throw new InternalError ( 62 "We strangly failed to retrieve methods that always exist on an object..."); 63 } 65 66 MethodInterceptor interceptor = new MethodInterceptor() { 67 public Object intercept(Object obj, Method method, Object [] args, 68 MethodProxy proxy) throws Throwable { 69 if (mockedMethods != null && !mockedMethods.contains(method)) { 70 return proxy.invokeSuper(obj, args); 71 } 72 return handler.invoke(obj, method, args); 73 } 74 }; 75 76 Enhancer enhancer = new Enhancer() { 78 82 protected void filterConstructors(Class sc, List constructors) { 83 CollectionUtils.filter(constructors, new VisibilityPredicate( 84 sc, true)); 85 } 86 }; 87 enhancer.setSuperclass(toMock); 88 enhancer.setCallbackType(interceptor.getClass()); 89 enhancer.setUseFactory(false); 93 enhancer.setUseCache(false); 97 98 Class mock = enhancer.createClass(); 99 Enhancer.registerCallbacks(mock, new Callback[] { interceptor }); 100 try { 101 return ClassInstantiatorFactory.getInstantiator().newInstance(mock); 102 } catch (InstantiationException e) { 103 throw new RuntimeException ("Fail to instantiate mock for " + toMock 105 + " on " + ClassInstantiatorFactory.getJVM() + " JVM"); 106 } 108 } 109 110 private void updateMethod(InvocationHandler objectMethodsFilter, 111 Method correctMethod) { 112 Field methodField = retrieveField(ObjectMethodsFilter.class, 113 correctMethod.getName() + "Method"); 114 updateField(objectMethodsFilter, correctMethod, methodField); 115 } 116 117 private Field retrieveField(Class clazz, String field) { 118 try { 119 return clazz.getDeclaredField(field); 120 } catch (NoSuchFieldException e) { 121 throw new InternalError ( 123 "There must be some refactoring because the " + field 124 + " field was there..."); 125 } 127 } 128 129 private void updateField(Object instance, Object value, Field field) { 130 boolean accessible = field.isAccessible(); 131 field.setAccessible(true); 132 try { 133 field.set(instance, value); 134 } catch (IllegalAccessException e) { 135 throw new InternalError ( 137 "Should be accessible since we set it ourselves"); 138 } 140 field.setAccessible(accessible); 141 } 142 } | Popular Tags |