1/*
2 * Javassist, a Java-bytecode translator toolkit.
3 * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved.
4 *
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License.  Alternatively, the contents of this file may be used under
8 * the terms of the GNU Lesser General Public License Version 2.1 or later.
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 */
15
16package javassist.bytecode;
17
18import java.io.PrintWriter;
19import javassist.Modifier;
20import java.util.List;
21
22/**
23 * A utility class for priting the contents of a class file.
24 * It prints a constant pool table, fields, and methods in a
25 * human readable representation.
26 */
27public class ClassFilePrinter {
28    /**
29     * Prints the contents of a class file to the standard output stream.
30     */
31    public static void print(ClassFile cf) {
32        print(cf, new PrintWriter(System.out, true));
33    }
34
35    /**
36     * Prints the contents of a class file.
37     */
38    public static void print(ClassFile cf, PrintWriter out) {
39        List list;
40        int n;
41
42        /* 0x0020 (SYNCHRONIZED) means ACC_SUPER if the modifiers
43         * are of a class.
44         */
45        int mod
46            = AccessFlag.toModifier(cf.getAccessFlags()
47                                    & ~AccessFlag.SYNCHRONIZED);
48        out.println("major: " + cf.major + ", minor: " + cf.minor
49                    + " modifiers: " + Integer.toHexString(cf.getAccessFlags()));
50        out.println(Modifier.toString(mod) + " class "
51                    + cf.getName() + " extends " + cf.getSuperclass());
52
53        String[] infs = cf.getInterfaces();
54        if (infs != null && infs.length > 0) {
55            out.print("    implements ");
56            out.print(infs[0]);
57            for (int i = 1; i < infs.length; ++i)
58                out.print(", " + infs[i]);
59
60            out.println();
61        }
62
63        out.println();
64        list = cf.getFields();
65        n = list.size();
66        for (int i = 0; i < n; ++i) {
67            FieldInfo finfo = (FieldInfo)list.get(i);
68            int acc = finfo.getAccessFlags();
69            out.println(Modifier.toString(AccessFlag.toModifier(acc))
70                        + " " + finfo.getName() + "\t"
71                        + finfo.getDescriptor());
72            printAttributes(finfo.getAttributes(), out, 'f');
73        }
74
75        out.println();
76        list = cf.getMethods();
77        n = list.size();
78        for (int i = 0; i < n; ++i) {
79            MethodInfo minfo = (MethodInfo)list.get(i);
80            int acc = minfo.getAccessFlags();
81            out.println(Modifier.toString(AccessFlag.toModifier(acc))
82                        + " " + minfo.getName() + "\t"
83                        + minfo.getDescriptor());
84            printAttributes(minfo.getAttributes(), out, 'm');
85            out.println();
86        }
87
88        out.println();
89        printAttributes(cf.getAttributes(), out, 'c');
90    }
91
92    static void printAttributes(List list, PrintWriter out, char kind) {
93        if (list == null)
94            return;
95
96        int n = list.size();
97        for (int i = 0; i < n; ++i) {
98            AttributeInfo ai = (AttributeInfo)list.get(i);
99            if (ai instanceof CodeAttribute) {
100                CodeAttribute ca = (CodeAttribute)ai;
101                out.println("attribute: " + ai.getName() + ": "
102                            + ai.getClass().getName());
103                out.println("max stack " + ca.getMaxStack()
104                            + ", max locals " + ca.getMaxLocals()
105                            + ", " + ca.getExceptionTable().size()
106                            + " catch blocks");
107                out.println("<code attribute begin>");
108                printAttributes(ca.getAttributes(), out, kind);
109                out.println("<code attribute end>");
110            }
111            else if (ai instanceof AnnotationsAttribute) {
112                out.println("annnotation: " + ai.toString());
113            }
114            else if (ai instanceof ParameterAnnotationsAttribute) {
115                out.println("parameter annnotations: " + ai.toString());
116            }
117            else if (ai instanceof StackMapTable) {
118                out.println("<stack map table begin>");
119                StackMapTable.Printer.print((StackMapTable)ai, out);
120                out.println("<stack map table end>");
121            }
122            else if (ai instanceof StackMap) {
123                out.println("<stack map begin>");
124                ((StackMap)ai).print(out);
125                out.println("<stack map end>");
126            }
127            else if (ai instanceof SignatureAttribute) {
128                SignatureAttribute sa = (SignatureAttribute)ai;
129                String sig = sa.getSignature();
130                out.println("signature: " + sig);
131                try {
132                    String s;
133                    if (kind == 'c')
134                        s = SignatureAttribute.toClassSignature(sig).toString();
135                    else if (kind == 'm')
136                        s = SignatureAttribute.toMethodSignature(sig).toString();
137                    else
138                        s = SignatureAttribute.toFieldSignature(sig).toString();
139
140                    out.println("           " + s);
141                }
142                catch (BadBytecode e) {
143                    out.println("           syntax error");
144                }
145            }
146            else
147                out.println("attribute: " + ai.getName()
148                            + " (" + ai.get().length + " byte): "
149                            + ai.getClass().getName());
150        }
151    }
152}
153