View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
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  		/*if (field.getAttributes().length == 0)
85  			out.print("\n");*/
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; // Remember for use in subsequent visitXXX calls
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) { // Special cases LOOKUPSWITCH and
141 											  // TABLESWITCH
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 { // LOOKUPSWITCH
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()); // Applies
162 																	  // for
163 																	  // both
164 				} else {
165 					BranchInstruction bi = (BranchInstruction) inst;
166 					ih = bi.getTarget();
167 					//str = get(ih);
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) ? // catch any exception, used
181 												   // when compiling finally
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