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.core;
17674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
18674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport java.io.*;
19674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport java.util.*;
20674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
21674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.asm.*;
22674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
23674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen/**
24674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @author Juozas Baliuka, Chris Nokleberg
25674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */
26674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenpublic class ClassEmitter extends ClassAdapter {
27674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private ClassInfo classInfo;
28674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private Map fieldInfo;
29674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
30674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private static int hookCounter;
31674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private MethodVisitor rawStaticInit;
32674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private CodeEmitter staticInit;
33674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private CodeEmitter staticHook;
34674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private Signature staticHookSig;
35674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
36674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public ClassEmitter(ClassVisitor cv) {
37674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        super(null);
38674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        setTarget(cv);
39674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
40674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
41674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public ClassEmitter() {
42674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        super(null);
43674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
44674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
45674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void setTarget(ClassVisitor cv) {
46674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        this.cv = cv;
47674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        fieldInfo = new HashMap();
48674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
49674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        // just to be safe
50674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        staticInit = staticHook = null;
51674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        staticHookSig = null;
52674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
53674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
54674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    synchronized private static int getNextHook() {
55674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return ++hookCounter;
56674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
57674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
58674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public ClassInfo getClassInfo() {
59674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return classInfo;
60674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
61674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
62674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void begin_class(int version, final int access, String className, final Type superType, final Type[] interfaces, String source) {
63674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        final Type classType = Type.getType("L" + className.replace('.', '/') + ";");
64674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        classInfo = new ClassInfo() {
65674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            public Type getType() {
66674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                return classType;
67674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
68674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            public Type getSuperType() {
69674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                return (superType != null) ? superType : Constants.TYPE_OBJECT;
70674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
71674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            public Type[] getInterfaces() {
72674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                return interfaces;
73674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
74674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            public int getModifiers() {
75674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                return access;
76674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
77674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        };
78674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        cv.visit(version,
79674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                 access,
80674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                 classInfo.getType().getInternalName(),
81674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                 null,
82674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                 classInfo.getSuperType().getInternalName(),
83674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                 TypeUtils.toInternalNames(interfaces));
84674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (source != null)
85674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            cv.visitSource(source, null);
86674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        init();
87674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
88674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
89674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public CodeEmitter getStaticHook() {
90674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen         if (TypeUtils.isInterface(getAccess())) {
91674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen             throw new IllegalStateException("static hook is invalid for this class");
92674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen         }
93674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen         if (staticHook == null) {
94674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen             staticHookSig = new Signature("CGLIB$STATICHOOK" + getNextHook(), "()V");
95674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen             staticHook = begin_method(Constants.ACC_STATIC,
96674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                       staticHookSig,
97674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                       null);
98674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen             if (staticInit != null) {
99674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                 staticInit.invoke_static_this(staticHookSig);
100674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen             }
101674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen         }
102674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen         return staticHook;
103674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
104674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
105674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    protected void init() {
106674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
107674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
108674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public int getAccess() {
109674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return classInfo.getModifiers();
110674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
111674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
112674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public Type getClassType() {
113674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return classInfo.getType();
114674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
115674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
116674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public Type getSuperType() {
117674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return classInfo.getSuperType();
118674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
119674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
120674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void end_class() {
121674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (staticHook != null && staticInit == null) {
122674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            // force creation of static init
123674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            begin_static();
124674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
125674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (staticInit != null) {
126674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            staticHook.return_value();
127674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            staticHook.end_method();
128674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            rawStaticInit.visitInsn(Constants.RETURN);
129674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            rawStaticInit.visitMaxs(0, 0);
130674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            staticInit = staticHook = null;
131674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            staticHookSig = null;
132674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
133674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        cv.visitEnd();
134674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
135674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
136674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public CodeEmitter begin_method(int access, Signature sig, Type[] exceptions) {
137674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (classInfo == null)
138674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalStateException("classInfo is null! " + this);
139674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        MethodVisitor v = cv.visitMethod(access,
140674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                         sig.getName(),
141674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                         sig.getDescriptor(),
142674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                         null,
143674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                         TypeUtils.toInternalNames(exceptions));
144674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (sig.equals(Constants.SIG_STATIC) && !TypeUtils.isInterface(getAccess())) {
145674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            rawStaticInit = v;
146674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            MethodVisitor wrapped = new MethodAdapter(v) {
147674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                public void visitMaxs(int maxStack, int maxLocals) {
148674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    // ignore
149674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
150674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                public void visitInsn(int insn) {
151674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    if (insn != Constants.RETURN) {
152674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                        super.visitInsn(insn);
153674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    }
154674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
155674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            };
156674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            staticInit = new CodeEmitter(this, wrapped, access, sig, exceptions);
157674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (staticHook == null) {
158674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                // force static hook creation
159674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                getStaticHook();
160674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            } else {
161674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                staticInit.invoke_static_this(staticHookSig);
162674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
163674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            return staticInit;
164674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        } else if (sig.equals(staticHookSig)) {
165674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            return new CodeEmitter(this, v, access, sig, exceptions) {
166674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                public boolean isStaticHook() {
167674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    return true;
168674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
169674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            };
170674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        } else {
171674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            return new CodeEmitter(this, v, access, sig, exceptions);
172674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
173674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
174674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
175674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public CodeEmitter begin_static() {
176674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return begin_method(Constants.ACC_STATIC, Constants.SIG_STATIC, null);
177674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
178674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
179674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void declare_field(int access, String name, Type type, Object value) {
180674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        FieldInfo existing = (FieldInfo)fieldInfo.get(name);
181674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        FieldInfo info = new FieldInfo(access, name, type, value);
182674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (existing != null) {
183674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (!info.equals(existing)) {
184674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                throw new IllegalArgumentException("Field \"" + name + "\" has been declared differently");
185674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
186674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        } else {
187674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            fieldInfo.put(name, info);
188674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            cv.visitField(access, name, type.getDescriptor(), null, value);
189674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
190674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
191674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
192674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // TODO: make public?
193674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    boolean isFieldDeclared(String name) {
194674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return fieldInfo.get(name) != null;
195674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
196674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
197674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    FieldInfo getFieldInfo(String name) {
198674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        FieldInfo field = (FieldInfo)fieldInfo.get(name);
199674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (field == null) {
200674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalArgumentException("Field " + name + " is not declared in " + getClassType().getClassName());
201674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
202674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return field;
203674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
204674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
205674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    static class FieldInfo {
206674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        int access;
207674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        String name;
208674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        Type type;
209674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        Object value;
210674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
211674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        public FieldInfo(int access, String name, Type type, Object value) {
212674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            this.access = access;
213674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            this.name = name;
214674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            this.type = type;
215674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            this.value = value;
216674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
217674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
218674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        public boolean equals(Object o) {
219674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (o == null)
220674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                return false;
221674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (!(o instanceof FieldInfo))
222674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                return false;
223674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            FieldInfo other = (FieldInfo)o;
224674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (access != other.access ||
225674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                !name.equals(other.name) ||
226674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                !type.equals(other.type)) {
227674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                return false;
228674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
229674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if ((value == null) ^ (other.value == null))
230674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                return false;
231674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (value != null && !value.equals(other.value))
232674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                return false;
233674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            return true;
234674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
235674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
236674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        public int hashCode() {
237674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            return access ^ name.hashCode() ^ type.hashCode() ^ ((value == null) ? 0 : value.hashCode());
238674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
239674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
240674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
241674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visit(int version,
242674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                      int access,
243674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                      String name,
244674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                      String signature,
245674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                      String superName,
246674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                      String[] interfaces) {
247674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        begin_class(version,
248674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    access,
249674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    name.replace('/', '.'),
250674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    TypeUtils.fromInternalName(superName),
251674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    TypeUtils.fromInternalNames(interfaces),
252674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    null); // TODO
253674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
254674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
255674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitEnd() {
256674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        end_class();
257674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
258674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
259674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public FieldVisitor visitField(int access,
260674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                   String name,
261674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                   String desc,
262674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                   String signature,
263674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                   Object value) {
264674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        declare_field(access, name, Type.getType(desc), value);
265674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return null; // TODO
266674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
267674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
268674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public MethodVisitor visitMethod(int access,
269674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                     String name,
270674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                     String desc,
271674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                     String signature,
272674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                                     String[] exceptions) {
273674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return begin_method(access,
274674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            new Signature(name, desc),
275674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                            TypeUtils.fromInternalNames(exceptions));
276674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
277674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen}
278