1674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen/* 2674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Copyright 2003 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.reflect; 17674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 18674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport java.lang.reflect.*; 19674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 20674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.asm.ClassVisitor; 21674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.asm.Type; 22674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.cglib.core.*; 23674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 24674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen/** 25674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @author Chris Nokleberg 26674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @version $Id: ConstructorDelegate.java,v 1.20 2006/03/05 02:43:19 herbyderby Exp $ 27674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 28674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenabstract public class ConstructorDelegate { 29674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final ConstructorKey KEY_FACTORY = 30674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen (ConstructorKey)KeyFactory.create(ConstructorKey.class, KeyFactory.CLASS_BY_NAME); 31674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 32674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen interface ConstructorKey { 33674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public Object newInstance(String declaring, String iface); 34674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 35674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 36674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen protected ConstructorDelegate() { 37674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 38674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 39674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public static ConstructorDelegate create(Class targetClass, Class iface) { 40674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Generator gen = new Generator(); 41674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen gen.setTargetClass(targetClass); 42674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen gen.setInterface(iface); 43674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return gen.create(); 44674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 45674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 46674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public static class Generator extends AbstractClassGenerator { 47674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Source SOURCE = new Source(ConstructorDelegate.class.getName()); 48674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Type CONSTRUCTOR_DELEGATE = 49674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen TypeUtils.parseType("org.mockito.cglib.reflect.ConstructorDelegate"); 50674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 51674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private Class iface; 52674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private Class targetClass; 53674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 54674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public Generator() { 55674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen super(SOURCE); 56674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 57674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 58674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void setInterface(Class iface) { 59674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen this.iface = iface; 60674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 61674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 62674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void setTargetClass(Class targetClass) { 63674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen this.targetClass = targetClass; 64674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 65674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 66674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public ConstructorDelegate create() { 67674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen setNamePrefix(targetClass.getName()); 68674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Object key = KEY_FACTORY.newInstance(iface.getName(), targetClass.getName()); 69674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return (ConstructorDelegate)super.create(key); 70674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 71674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 72674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen protected ClassLoader getDefaultClassLoader() { 73674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return targetClass.getClassLoader(); 74674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 75674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 76674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void generateClass(ClassVisitor v) { 77674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen setNamePrefix(targetClass.getName()); 78674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 79674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Method newInstance = ReflectUtils.findNewInstance(iface); 80674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (!newInstance.getReturnType().isAssignableFrom(targetClass)) { 81674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw new IllegalArgumentException("incompatible return type"); 82674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 83674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Constructor constructor; 84674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen try { 85674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen constructor = targetClass.getDeclaredConstructor(newInstance.getParameterTypes()); 86674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } catch (NoSuchMethodException e) { 87674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw new IllegalArgumentException("interface does not match any known constructor"); 88674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 89674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 90674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ClassEmitter ce = new ClassEmitter(v); 91674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ce.begin_class(Constants.V1_2, 92674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Constants.ACC_PUBLIC, 93674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen getClassName(), 94674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen CONSTRUCTOR_DELEGATE, 95674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen new Type[]{ Type.getType(iface) }, 96674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Constants.SOURCE_FILE); 97674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Type declaring = Type.getType(constructor.getDeclaringClass()); 98674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen EmitUtils.null_constructor(ce); 99674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, 100674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ReflectUtils.getSignature(newInstance), 101674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ReflectUtils.getExceptionTypes(newInstance)); 102674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.new_instance(declaring); 103674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.dup(); 104674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_args(); 105674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_constructor(declaring, ReflectUtils.getSignature(constructor)); 106674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.return_value(); 107674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.end_method(); 108674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ce.end_class(); 109674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 110674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 111674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen protected Object firstInstance(Class type) { 112674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return ReflectUtils.newInstance(type); 113674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 114674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 115674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen protected Object nextInstance(Object instance) { 116674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return instance; 117674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 118674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 119674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen} 120