169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/*
269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Javassist, a Java-bytecode translator toolkit.
369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved.
469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The contents of this file are subject to the Mozilla Public License Version
669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1.1 (the "License"); you may not use this file except in compliance with
769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the License.  Alternatively, the contents of this file may be used under
869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the terms of the GNU Lesser General Public License Version 2.1 or later.
969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
1069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Software distributed under the License is distributed on an "AS IS" basis,
1169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
1269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * for the specific language governing rights and limitations under the
1369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * License.
1469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */
1569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
1669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpackage javassist.bytecode;
1769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
1869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.PrintWriter;
1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.Modifier;
2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.util.List;
2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/**
2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * A utility class for priting the contents of a class file.
2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * It prints a constant pool table, fields, and methods in a
2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * human readable representation.
2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */
2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic class ClassFilePrinter {
2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Prints the contents of a class file to the standard output stream.
3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static void print(ClassFile cf) {
3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        print(cf, new PrintWriter(System.out, true));
3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Prints the contents of a class file.
3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static void print(ClassFile cf, PrintWriter out) {
3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        List list;
4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int n;
4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /* 0x0020 (SYNCHRONIZED) means ACC_SUPER if the modifiers
4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * are of a class.
4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int mod
4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            = AccessFlag.toModifier(cf.getAccessFlags()
4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                    & ~AccessFlag.SYNCHRONIZED);
4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        out.println("major: " + cf.major + ", minor: " + cf.minor
4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    + " modifiers: " + Integer.toHexString(cf.getAccessFlags()));
5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        out.println(Modifier.toString(mod) + " class "
5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    + cf.getName() + " extends " + cf.getSuperclass());
5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String[] infs = cf.getInterfaces();
5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (infs != null && infs.length > 0) {
5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            out.print("    implements ");
5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            out.print(infs[0]);
5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            for (int i = 1; i < infs.length; ++i)
5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                out.print(", " + infs[i]);
5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            out.println();
6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        out.println();
6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        list = cf.getFields();
6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        n = list.size();
6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < n; ++i) {
6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            FieldInfo finfo = (FieldInfo)list.get(i);
6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int acc = finfo.getAccessFlags();
6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            out.println(Modifier.toString(AccessFlag.toModifier(acc))
7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        + " " + finfo.getName() + "\t"
7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        + finfo.getDescriptor());
7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            printAttributes(finfo.getAttributes(), out, 'f');
7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        out.println();
7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        list = cf.getMethods();
7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        n = list.size();
7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < n; ++i) {
7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            MethodInfo minfo = (MethodInfo)list.get(i);
8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int acc = minfo.getAccessFlags();
8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            out.println(Modifier.toString(AccessFlag.toModifier(acc))
8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        + " " + minfo.getName() + "\t"
8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        + minfo.getDescriptor());
8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            printAttributes(minfo.getAttributes(), out, 'm');
8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            out.println();
8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        out.println();
8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        printAttributes(cf.getAttributes(), out, 'c');
9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    static void printAttributes(List list, PrintWriter out, char kind) {
9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (list == null)
9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return;
9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int n = list.size();
9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < n; ++i) {
9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            AttributeInfo ai = (AttributeInfo)list.get(i);
9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (ai instanceof CodeAttribute) {
10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                CodeAttribute ca = (CodeAttribute)ai;
10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                out.println("attribute: " + ai.getName() + ": "
10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                            + ai.getClass().getName());
10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                out.println("max stack " + ca.getMaxStack()
10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                            + ", max locals " + ca.getMaxLocals()
10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                            + ", " + ca.getExceptionTable().size()
10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                            + " catch blocks");
10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                out.println("<code attribute begin>");
10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                printAttributes(ca.getAttributes(), out, kind);
10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                out.println("<code attribute end>");
11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else if (ai instanceof AnnotationsAttribute) {
11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                out.println("annnotation: " + ai.toString());
11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else if (ai instanceof ParameterAnnotationsAttribute) {
11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                out.println("parameter annnotations: " + ai.toString());
11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else if (ai instanceof StackMapTable) {
11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                out.println("<stack map table begin>");
11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                StackMapTable.Printer.print((StackMapTable)ai, out);
12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                out.println("<stack map table end>");
12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else if (ai instanceof StackMap) {
12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                out.println("<stack map begin>");
12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                ((StackMap)ai).print(out);
12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                out.println("<stack map end>");
12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else if (ai instanceof SignatureAttribute) {
12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                SignatureAttribute sa = (SignatureAttribute)ai;
12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                String sig = sa.getSignature();
13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                out.println("signature: " + sig);
13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                try {
13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    String s;
13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    if (kind == 'c')
13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        s = SignatureAttribute.toClassSignature(sig).toString();
13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    else if (kind == 'm')
13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        s = SignatureAttribute.toMethodSignature(sig).toString();
13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    else
13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        s = SignatureAttribute.toFieldSignature(sig).toString();
13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    out.println("           " + s);
14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                catch (BadBytecode e) {
14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    out.println("           syntax error");
14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else
14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                out.println("attribute: " + ai.getName()
14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                            + " (" + ai.get().length + " byte): "
14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                            + ai.getClass().getName());
15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
15269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal}
153