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.lang.reflect.Method;
19674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport java.util.*;
20674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
21674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.asm.ClassVisitor;
22674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.asm.Type;
23674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.cglib.core.*;
24674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
25674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen/**
26674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @author Chris Nokleberg
27674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @version $Id: MixinEmitter.java,v 1.9 2006/08/27 21:04:37 herbyderby Exp $
28674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */
29674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenclass MixinEmitter extends ClassEmitter {
30674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private static final String FIELD_NAME = "CGLIB$DELEGATES";
31674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private static final Signature CSTRUCT_OBJECT_ARRAY =
32674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen      TypeUtils.parseConstructor("Object[]");
33674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private static final Type MIXIN =
34674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen      TypeUtils.parseType("org.mockito.cglib.proxy.Mixin");
35674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private static final Signature NEW_INSTANCE =
36674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen      new Signature("newInstance", MIXIN, new Type[]{ Constants.TYPE_OBJECT_ARRAY });
37674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
38674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public MixinEmitter(ClassVisitor v, String className, Class[] classes, int[] route) {
39674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        super(v);
40674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
41674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        begin_class(Constants.V1_2,
42674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    Constants.ACC_PUBLIC,
43674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    className,
44674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    MIXIN,
45674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    TypeUtils.getTypes(getInterfaces(classes)),
46674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    Constants.SOURCE_FILE);
47674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        EmitUtils.null_constructor(this);
48674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        EmitUtils.factory_method(this, NEW_INSTANCE);
49674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
50674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        declare_field(Constants.ACC_PRIVATE, FIELD_NAME, Constants.TYPE_OBJECT_ARRAY, null);
51674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
52674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        CodeEmitter e = begin_method(Constants.ACC_PUBLIC, CSTRUCT_OBJECT_ARRAY, null);
53674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        e.load_this();
54674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        e.super_invoke_constructor();
55674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        e.load_this();
56674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        e.load_arg(0);
57674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        e.putfield(FIELD_NAME);
58674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        e.return_value();
59674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        e.end_method();
60674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
61674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        Set unique = new HashSet();
62674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        for (int i = 0; i < classes.length; i++) {
63674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            Method[] methods = getMethods(classes[i]);
64674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            for (int j = 0; j < methods.length; j++) {
65674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                if (unique.add(MethodWrapper.create(methods[j]))) {
66674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    MethodInfo method = ReflectUtils.getMethodInfo(methods[j]);
67674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    e = EmitUtils.begin_method(this, method, Constants.ACC_PUBLIC);
68674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    e.load_this();
69674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    e.getfield(FIELD_NAME);
70674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    e.aaload((route != null) ? route[i] : i);
71674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    e.checkcast(method.getClassInfo().getType());
72674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    e.load_args();
73674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    e.invoke(method);
74674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    e.return_value();
75674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    e.end_method();
76674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
77674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
78674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
79674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
80674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        end_class();
81674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
82674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
83674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    protected Class[] getInterfaces(Class[] classes) {
84674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return classes;
85674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
86674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
87674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    protected Method[] getMethods(Class type) {
88674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return type.getMethods();
89674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
90674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen}
91