1674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen/* 2674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Copyright 2003,2004 The Apache Software Foundation 3674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 4674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Licensed under the Apache License, Version 2.0 (the "License"); 5674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * you may not use this file except in compliance with the License. 6674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * You may obtain a copy of the License at 7674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 8674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * http://www.apache.org/licenses/LICENSE-2.0 9674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 10674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Unless required by applicable law or agreed to in writing, software 11674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * distributed under the License is distributed on an "AS IS" BASIS, 12674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * See the License for the specific language governing permissions and 14674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * limitations under the License. 15674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 16674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenpackage org.mockito.cglib.proxy; 17674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 18674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport java.io.Serializable; 19674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport java.lang.reflect.Method; 20674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport java.util.List; 21674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 22674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.cglib.core.CodeGenerationException; 23674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 24674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen/** 25674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * This class is meant to be used as replacement for 26674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * <code>java.lang.reflect.Proxy</code> under JDK 1.2. There are some known 27674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * subtle differences: 28674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * <ul> 29674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * <li>The exceptions returned by invoking <code>getExceptionTypes</code> 30674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * on the <code>Method</code> passed to the <code>invoke</code> method 31674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * <b>are</b> the exact set that can be thrown without resulting in an 32674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * <code>UndeclaredThrowableException</code> being thrown. 33674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * <li>{@link UndeclaredThrowableException} is used instead 34674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * of <code>java.lang.reflect.UndeclaredThrowableException</code>. 35674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * </ul> 36674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * <p> 37674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @version $Id: Proxy.java,v 1.6 2004/06/24 21:15:19 herbyderby Exp $ 38674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 39674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenpublic class Proxy implements Serializable { 40674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen protected InvocationHandler h; 41674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 42674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final CallbackFilter BAD_OBJECT_METHOD_FILTER = new CallbackFilter() { 43674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public int accept(Method method, List<Method> allMethods) { 44674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (method.getDeclaringClass().getName().equals("java.lang.Object")) { 45674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen String name = method.getName(); 46674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (!(name.equals("hashCode") || 47674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen name.equals("equals") || 48674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen name.equals("toString"))) { 49674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return 1; 50674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 51674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 52674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return 0; 53674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 54674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen }; 55674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 56674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen protected Proxy(InvocationHandler h) { 57674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Enhancer.registerCallbacks(getClass(), new Callback[]{ h, null }); 58674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen this.h = h; 59674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 60674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 61674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // private for security of isProxyClass 62674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static class ProxyImpl extends Proxy { 63674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen protected ProxyImpl(InvocationHandler h) { 64674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen super(h); 65674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 66674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 67674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 68674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public static InvocationHandler getInvocationHandler(Object proxy) { 69674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (!(proxy instanceof ProxyImpl)) { 70674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw new IllegalArgumentException("Object is not a proxy"); 71674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 72674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return ((Proxy)proxy).h; 73674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 74674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 75674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public static Class getProxyClass(ClassLoader loader, Class[] interfaces) { 76674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Enhancer e = new Enhancer(); 77674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.setSuperclass(ProxyImpl.class); 78674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.setInterfaces(interfaces); 79674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.setCallbackTypes(new Class[]{ 80674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen InvocationHandler.class, 81674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen NoOp.class, 82674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen }); 83674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.setCallbackFilter(BAD_OBJECT_METHOD_FILTER); 84674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.setUseFactory(false); 85674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return e.createClass(); 86674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 87674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 88674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public static boolean isProxyClass(Class cl) { 89674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return cl.getSuperclass().equals(ProxyImpl.class); 90674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 91674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 92674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h) { 93674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen try { 94674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Class clazz = getProxyClass(loader, interfaces); 95674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return clazz.getConstructor(new Class[]{ InvocationHandler.class }).newInstance(new Object[]{ h }); 96674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } catch (RuntimeException e) { 97674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw e; 98674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } catch (Exception e) { 99674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw new CodeGenerationException(e); 100674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 101674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 102674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen} 103