1/***
2 * ASM: a very small and fast Java bytecode manipulation framework
3 * Copyright (c) 2000-2007 INRIA, France Telecom
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the copyright holders nor the names of its
15 *    contributors may be used to endorse or promote products derived from
16 *    this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28 * THE POSSIBILITY OF SUCH DAMAGE.
29 */
30package org.mockito.asm.tree;
31
32import org.mockito.asm.Attribute;
33import org.mockito.asm.ClassVisitor;
34import org.mockito.asm.FieldVisitor;
35import org.mockito.asm.MethodVisitor;
36
37import java.util.List;
38import java.util.ArrayList;
39import java.util.Arrays;
40
41/**
42 * A node that represents a class.
43 *
44 * @author Eric Bruneton
45 */
46public class ClassNode extends MemberNode implements ClassVisitor {
47
48    /**
49     * The class version.
50     */
51    public int version;
52
53    /**
54     * The class's access flags (see {@link org.mockito.asm.Opcodes}). This
55     * field also indicates if the class is deprecated.
56     */
57    public int access;
58
59    /**
60     * The internal name of the class (see
61     * {@link org.mockito.asm.Type#getInternalName() getInternalName}).
62     */
63    public String name;
64
65    /**
66     * The signature of the class. Mayt be <tt>null</tt>.
67     */
68    public String signature;
69
70    /**
71     * The internal of name of the super class (see
72     * {@link org.mockito.asm.Type#getInternalName() getInternalName}). For
73     * interfaces, the super class is {@link Object}. May be <tt>null</tt>,
74     * but only for the {@link Object} class.
75     */
76    public String superName;
77
78    /**
79     * The internal names of the class's interfaces (see
80     * {@link org.mockito.asm.Type#getInternalName() getInternalName}). This
81     * list is a list of {@link String} objects.
82     */
83    public List interfaces;
84
85    /**
86     * The name of the source file from which this class was compiled. May be
87     * <tt>null</tt>.
88     */
89    public String sourceFile;
90
91    /**
92     * Debug information to compute the correspondance between source and
93     * compiled elements of the class. May be <tt>null</tt>.
94     */
95    public String sourceDebug;
96
97    /**
98     * The internal name of the enclosing class of the class. May be
99     * <tt>null</tt>.
100     */
101    public String outerClass;
102
103    /**
104     * The name of the method that contains the class, or <tt>null</tt> if the
105     * class is not enclosed in a method.
106     */
107    public String outerMethod;
108
109    /**
110     * The descriptor of the method that contains the class, or <tt>null</tt>
111     * if the class is not enclosed in a method.
112     */
113    public String outerMethodDesc;
114
115    /**
116     * Informations about the inner classes of this class. This list is a list
117     * of {@link InnerClassNode} objects.
118     *
119     * @associates org.mockito.asm.tree.InnerClassNode
120     */
121    public List innerClasses;
122
123    /**
124     * The fields of this class. This list is a list of {@link FieldNode}
125     * objects.
126     *
127     * @associates org.mockito.asm.tree.FieldNode
128     */
129    public List fields;
130
131    /**
132     * The methods of this class. This list is a list of {@link MethodNode}
133     * objects.
134     *
135     * @associates org.mockito.asm.tree.MethodNode
136     */
137    public List methods;
138
139    /**
140     * Constructs a new {@link ClassNode}.
141     */
142    public ClassNode() {
143        this.interfaces = new ArrayList();
144        this.innerClasses = new ArrayList();
145        this.fields = new ArrayList();
146        this.methods = new ArrayList();
147    }
148
149    // ------------------------------------------------------------------------
150    // Implementation of the ClassVisitor interface
151    // ------------------------------------------------------------------------
152
153    public void visit(
154        final int version,
155        final int access,
156        final String name,
157        final String signature,
158        final String superName,
159        final String[] interfaces)
160    {
161        this.version = version;
162        this.access = access;
163        this.name = name;
164        this.signature = signature;
165        this.superName = superName;
166        if (interfaces != null) {
167            this.interfaces.addAll(Arrays.asList(interfaces));
168        }
169    }
170
171    public void visitSource(final String file, final String debug) {
172        sourceFile = file;
173        sourceDebug = debug;
174    }
175
176    public void visitOuterClass(
177        final String owner,
178        final String name,
179        final String desc)
180    {
181        outerClass = owner;
182        outerMethod = name;
183        outerMethodDesc = desc;
184    }
185
186    public void visitInnerClass(
187        final String name,
188        final String outerName,
189        final String innerName,
190        final int access)
191    {
192        InnerClassNode icn = new InnerClassNode(name,
193                outerName,
194                innerName,
195                access);
196        innerClasses.add(icn);
197    }
198
199    public FieldVisitor visitField(
200        final int access,
201        final String name,
202        final String desc,
203        final String signature,
204        final Object value)
205    {
206        FieldNode fn = new FieldNode(access, name, desc, signature, value);
207        fields.add(fn);
208        return fn;
209    }
210
211    public MethodVisitor visitMethod(
212        final int access,
213        final String name,
214        final String desc,
215        final String signature,
216        final String[] exceptions)
217    {
218        MethodNode mn = new MethodNode(access,
219                name,
220                desc,
221                signature,
222                exceptions);
223        methods.add(mn);
224        return mn;
225    }
226
227    // ------------------------------------------------------------------------
228    // Accept method
229    // ------------------------------------------------------------------------
230
231    /**
232     * Makes the given class visitor visit this class.
233     *
234     * @param cv a class visitor.
235     */
236    public void accept(final ClassVisitor cv) {
237        // visits header
238        String[] interfaces = new String[this.interfaces.size()];
239        this.interfaces.toArray(interfaces);
240        cv.visit(version, access, name, signature, superName, interfaces);
241        // visits source
242        if (sourceFile != null || sourceDebug != null) {
243            cv.visitSource(sourceFile, sourceDebug);
244        }
245        // visits outer class
246        if (outerClass != null) {
247            cv.visitOuterClass(outerClass, outerMethod, outerMethodDesc);
248        }
249        // visits attributes
250        int i, n;
251        n = visibleAnnotations == null ? 0 : visibleAnnotations.size();
252        for (i = 0; i < n; ++i) {
253            AnnotationNode an = (AnnotationNode) visibleAnnotations.get(i);
254            an.accept(cv.visitAnnotation(an.desc, true));
255        }
256        n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size();
257        for (i = 0; i < n; ++i) {
258            AnnotationNode an = (AnnotationNode) invisibleAnnotations.get(i);
259            an.accept(cv.visitAnnotation(an.desc, false));
260        }
261        n = attrs == null ? 0 : attrs.size();
262        for (i = 0; i < n; ++i) {
263            cv.visitAttribute((Attribute) attrs.get(i));
264        }
265        // visits inner classes
266        for (i = 0; i < innerClasses.size(); ++i) {
267            ((InnerClassNode) innerClasses.get(i)).accept(cv);
268        }
269        // visits fields
270        for (i = 0; i < fields.size(); ++i) {
271            ((FieldNode) fields.get(i)).accept(cv);
272        }
273        // visits methods
274        for (i = 0; i < methods.size(); ++i) {
275            ((MethodNode) methods.get(i)).accept(cv);
276        }
277        // visits end
278        cv.visitEnd();
279    }
280}
281