1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.javaflow.bytecode.transformation.bcel;
18
19 import java.io.OutputStream;
20 import java.io.PrintWriter;
21
22 import org.apache.bcel.Constants;
23 import org.apache.bcel.classfile.Code;
24 import org.apache.bcel.classfile.ConstantValue;
25 import org.apache.bcel.classfile.Deprecated;
26 import org.apache.bcel.classfile.ExceptionTable;
27 import org.apache.bcel.classfile.Field;
28 import org.apache.bcel.classfile.JavaClass;
29 import org.apache.bcel.classfile.Method;
30 import org.apache.bcel.classfile.Synthetic;
31 import org.apache.bcel.classfile.Utility;
32 import org.apache.bcel.generic.BranchInstruction;
33 import org.apache.bcel.generic.CodeExceptionGen;
34 import org.apache.bcel.generic.ConstantPoolGen;
35 import org.apache.bcel.generic.Instruction;
36 import org.apache.bcel.generic.InstructionHandle;
37 import org.apache.bcel.generic.InstructionList;
38 import org.apache.bcel.generic.LocalVariableGen;
39 import org.apache.bcel.generic.MethodGen;
40 import org.apache.bcel.generic.ObjectType;
41 import org.apache.bcel.generic.Select;
42 import org.apache.bcel.generic.TABLESWITCH;
43
44 public final class DecompilingVisitor extends org.apache.bcel.classfile.EmptyVisitor {
45 private JavaClass clazz;
46 private PrintWriter out;
47 private String clazzname;
48 private ConstantPoolGen cp;
49
50 public DecompilingVisitor(JavaClass clazz, OutputStream out) {
51 this.clazz = clazz;
52 this.out = new PrintWriter(out);
53 clazzname = clazz.getClassName();
54 cp = new ConstantPoolGen(clazz.getConstantPool());
55 }
56
57 public void start() {
58 new org.apache.bcel.classfile.DescendingVisitor(clazz, this).visit();
59 out.close();
60 }
61
62 public void visitJavaClass(JavaClass clazz) {
63
64 out.println("// source " + clazz.getSourceFileName());
65 out.println(Utility.accessToString(clazz.getAccessFlags(), true) + " "
66 + Utility.classOrInterface(clazz.getAccessFlags()) + " "
67 + clazz.getClassName().replace('.', '/'));
68 out.println(" extends " + clazz.getSuperclassName().replace('.', '/'));
69
70 String[] interfaces = clazz.getInterfaceNames();
71
72 if (interfaces.length > 0) {
73 out.print(" implements");
74 for (int i = 0; i < interfaces.length; i++)
75 out.print(" " + interfaces[i].replace('.', '/'));
76 out.println();
77 }
78 out.println();
79 }
80
81 public void visitField(Field field) {
82 out.println(" " + Utility.accessToString(field.getAccessFlags()) + " "
83 + field.getType() + " " + field.getName() + ";");
84
85
86 }
87
88 public void visitConstantValue(ConstantValue cv) {
89 out.println(" = " + cv);
90 }
91
92 private Method _method;
93
94 public void visitDeprecated(Deprecated attribute) {
95 }
96
97 public void visitSynthetic(Synthetic attribute) {
98 }
99
100 public void visitMethod(Method method) {
101 this._method = method;
102
103 out.println("\n " + Utility.accessToString(_method.getAccessFlags())
104 + " " + _method.getReturnType() + " " + _method.getName());
105
106 }
107
108 public void visitExceptionTable(ExceptionTable e) {
109 String[] names = e.getExceptionNames();
110 for (int i = 0; i < names.length; i++)
111 out.println(" throws " + names[i].replace('.', '/'));
112 }
113
114 public void visitCode(Code code) {
115 MethodGen mg = new MethodGen(_method, clazzname, cp);
116 InstructionList il = mg.getInstructionList();
117 InstructionHandle[] ihs = il.getInstructionHandles();
118
119 LocalVariableGen[] lvs = mg.getLocalVariables();
120
121 CodeExceptionGen[] ehs = mg.getExceptionHandlers();
122
123 for (int i = 0; i < lvs.length; i++) {
124 LocalVariableGen l = lvs[i];
125 out.println(" // local variable " + l.getIndex() + " is \"" + l.getName()
126 + "\" " + l.getType() + " from "
127 + l.getStart().getPosition() + " to "
128 + l.getEnd().getPosition());
129 }
130
131 out.print("\n");
132
133 for (int i = 0; i < ihs.length; i++) {
134 InstructionHandle ih = ihs[i];
135 Instruction inst = ih.getInstruction();
136
137 out.print(" " + ih.getPosition());
138
139 if (inst instanceof BranchInstruction) {
140 if (inst instanceof Select) {
141
142 Select s = (Select) inst;
143 int[] matchs = s.getMatchs();
144 InstructionHandle[] targets = s.getTargets();
145
146 if (s instanceof TABLESWITCH) {
147 out.println(" tableswitch " + matchs[0] + " "
148 + matchs[matchs.length - 1]);
149
150 for (int j = 0; j < targets.length; j++)
151 out.println(" " + targets[j].getPosition());
152
153 } else {
154 out.println(" lookupswitch ");
155
156 for (int j = 0; j < targets.length; j++)
157 out.println(" " + matchs[j] + " : "
158 + targets[j].getPosition());
159 }
160
161 out.println(" default: " + s.getTarget());
162
163
164 } else {
165 BranchInstruction bi = (BranchInstruction) inst;
166 ih = bi.getTarget();
167
168 out.println(" " + Constants.OPCODE_NAMES[bi.getOpcode()]
169 + " " + ih);
170 }
171 } else
172 out.println(" " + inst.toString(cp.getConstantPool()));
173 }
174
175 out.print("\n");
176
177 for (int i = 0; i < ehs.length; i++) {
178 CodeExceptionGen c = ehs[i];
179 ObjectType caught = c.getCatchType();
180 String class_name = (caught == null) ?
181
182 "all" : caught.getClassName().replace('.', '/');
183
184 out.println(" catch " + class_name + " from "
185 + c.getStartPC().getPosition() + " to "
186 + c.getEndPC().getPosition() + " using "
187 + c.getHandlerPC().getPosition());
188 }
189 }
190 }
191