MixinEmitter.java revision 674060f01e9090cd21b3c5656cc3204912ad17a6
1/* 2 * Copyright 2003,2004 The Apache Software Foundation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16package org.mockito.cglib.proxy; 17 18import java.lang.reflect.Method; 19import java.util.*; 20 21import org.mockito.asm.ClassVisitor; 22import org.mockito.asm.Type; 23import org.mockito.cglib.core.*; 24 25/** 26 * @author Chris Nokleberg 27 * @version $Id: MixinEmitter.java,v 1.9 2006/08/27 21:04:37 herbyderby Exp $ 28 */ 29class MixinEmitter extends ClassEmitter { 30 private static final String FIELD_NAME = "CGLIB$DELEGATES"; 31 private static final Signature CSTRUCT_OBJECT_ARRAY = 32 TypeUtils.parseConstructor("Object[]"); 33 private static final Type MIXIN = 34 TypeUtils.parseType("org.mockito.cglib.proxy.Mixin"); 35 private static final Signature NEW_INSTANCE = 36 new Signature("newInstance", MIXIN, new Type[]{ Constants.TYPE_OBJECT_ARRAY }); 37 38 public MixinEmitter(ClassVisitor v, String className, Class[] classes, int[] route) { 39 super(v); 40 41 begin_class(Constants.V1_2, 42 Constants.ACC_PUBLIC, 43 className, 44 MIXIN, 45 TypeUtils.getTypes(getInterfaces(classes)), 46 Constants.SOURCE_FILE); 47 EmitUtils.null_constructor(this); 48 EmitUtils.factory_method(this, NEW_INSTANCE); 49 50 declare_field(Constants.ACC_PRIVATE, FIELD_NAME, Constants.TYPE_OBJECT_ARRAY, null); 51 52 CodeEmitter e = begin_method(Constants.ACC_PUBLIC, CSTRUCT_OBJECT_ARRAY, null); 53 e.load_this(); 54 e.super_invoke_constructor(); 55 e.load_this(); 56 e.load_arg(0); 57 e.putfield(FIELD_NAME); 58 e.return_value(); 59 e.end_method(); 60 61 Set unique = new HashSet(); 62 for (int i = 0; i < classes.length; i++) { 63 Method[] methods = getMethods(classes[i]); 64 for (int j = 0; j < methods.length; j++) { 65 if (unique.add(MethodWrapper.create(methods[j]))) { 66 MethodInfo method = ReflectUtils.getMethodInfo(methods[j]); 67 e = EmitUtils.begin_method(this, method, Constants.ACC_PUBLIC); 68 e.load_this(); 69 e.getfield(FIELD_NAME); 70 e.aaload((route != null) ? route[i] : i); 71 e.checkcast(method.getClassInfo().getType()); 72 e.load_args(); 73 e.invoke(method); 74 e.return_value(); 75 e.end_method(); 76 } 77 } 78 } 79 80 end_class(); 81 } 82 83 protected Class[] getInterfaces(Class[] classes) { 84 return classes; 85 } 86 87 protected Method[] getMethods(Class type) { 88 return type.getMethods(); 89 } 90} 91