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.util.*;
19674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
20674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.asm.Label;
21674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.asm.Type;
22674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.cglib.core.*;
23674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
24674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenclass LazyLoaderGenerator implements CallbackGenerator {
25674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public static final LazyLoaderGenerator INSTANCE = new LazyLoaderGenerator();
26674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
27674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private static final Signature LOAD_OBJECT =
28674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen      TypeUtils.parseSignature("Object loadObject()");
29674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private static final Type LAZY_LOADER =
30674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen      TypeUtils.parseType("org.mockito.cglib.proxy.LazyLoader");
31674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
32674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void generate(ClassEmitter ce, Context context, List methods) {
33674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        Set indexes = new HashSet();
34674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        for (Iterator it = methods.iterator(); it.hasNext();) {
35674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            MethodInfo method = (MethodInfo)it.next();
36674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (TypeUtils.isProtected(method.getModifiers())) {
37674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // ignore protected methods
38674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            } else {
39674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                int index = context.getIndex(method);
40674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                indexes.add(new Integer(index));
41674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                CodeEmitter e = context.beginMethod(ce, method);
42674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                e.load_this();
43674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                e.dup();
44674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                e.invoke_virtual_this(loadMethod(index));
45674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                e.checkcast(method.getClassInfo().getType());
46674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                e.load_args();
47674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                e.invoke(method);
48674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                e.return_value();
49674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                e.end_method();
50674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
51674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
52674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
53674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        for (Iterator it = indexes.iterator(); it.hasNext();) {
54674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            int index = ((Integer)it.next()).intValue();
55674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
56674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            String delegate = "CGLIB$LAZY_LOADER_" + index;
57674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            ce.declare_field(Constants.ACC_PRIVATE, delegate, Constants.TYPE_OBJECT, null);
58674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
59674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            CodeEmitter e = ce.begin_method(Constants.ACC_PRIVATE |
60674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                            Constants.ACC_SYNCHRONIZED |
61674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                            Constants.ACC_FINAL,
62674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                            loadMethod(index),
63674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                            null);
64674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            e.load_this();
65674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            e.getfield(delegate);
66674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            e.dup();
67674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            Label end = e.make_label();
68674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            e.ifnonnull(end);
69674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            e.pop();
70674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            e.load_this();
71674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            context.emitCallback(e, index);
72674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            e.invoke_interface(LAZY_LOADER, LOAD_OBJECT);
73674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            e.dup_x1();
74674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            e.putfield(delegate);
75674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            e.mark(end);
76674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            e.return_value();
77674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            e.end_method();
78674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
79674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
80674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
81674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
82674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private Signature loadMethod(int index) {
83674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return new Signature("CGLIB$LOAD_PRIVATE_" + index,
84674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                             Constants.TYPE_OBJECT,
85674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                             Constants.TYPES_EMPTY);
86674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
87674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
88674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void generateStatic(CodeEmitter e, Context context, List methods) { }
89674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen}
90