KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > de > uka > ipd > coverage > utils > ByteCodePrinter


1 /*
2  * Created on Aug 13, 2004
3  * @author Matthias Kempka
4  */

5 package de.uka.ipd.coverage.utils;
6
7
8 import java.io.*;
9 import java.util.*;
10
11 import org.apache.bcel.classfile.*;
12 import org.apache.bcel.generic.*;
13
14 /**
15  * The ByteCodePrinter can print the bytecode of all or given methods of a
16  * <code>org.apache.bcel.classfile.JavaClass</code> object.
17  * @author Matthias Kempka
18  *
19  */

20 public class ByteCodePrinter {
21
22     private static SafeStringArray sourcecode = new SafeStringArray();
23     private JavaClass jclass;
24
25     public ByteCodePrinter(JavaClass jclass) {
26         this.jclass = jclass;
27         sourcecode.setStringArray(openSource(jclass));
28     }
29     
30     /**
31      * print the bytecode of the parameter jclass to <code>System.out</code>
32      * in human readable form.<br>
33      * This method walks through all methods of the given class and prints out
34      * the instruction number, the corresponding source code line, the byte code,
35      * and, if it can be found, the source code.
36      */

37     public void printBytecode() {
38         printBytecode(System.out);
39     }
40     
41     public void printBytecode(PrintStream out, boolean indicateBranches) {
42         Method[] methods = jclass.getMethods();
43         for (int i = 0; i < methods.length; i++) {
44             printBytecode(out, methods[i], indicateBranches);
45         }
46     }
47     
48     public void printBytecode(PrintStream out) {
49         printBytecode(out, true);
50     }
51
52     public void printBytecode(PrintStream out, Method method, boolean indicateBranches) {
53         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
54         sb.append("\n\nKlasse: " + jclass.getClassName() + " Source: " + jclass.getSourceFileName()); //$NON-NLS-1$ //$NON-NLS-2$
55
sb.append("\nMethode: " + method.getName() + ":"); //$NON-NLS-1$ //$NON-NLS-2$
56
Code code = method.getCode();
57         printByteCode(out, sb.toString(), code, indicateBranches, true);
58     }
59
60     /**
61      * @param indicateBranches
62      * @param sourcecode
63      * @param code
64      * @param lastsourceline
65      * @param element
66      * @param pos
67      * @param sourceLine
68      */

69     private static String JavaDoc createOutputLine(boolean indicateBranches,
70             boolean showPositions,
71             SafeStringArray sourcecode, Code code, int lastsourceline,
72             InstructionHandle element, int pos, int sourceLine) {
73         List outputParams = createOutputParams(sourcecode,
74                                                 code,
75                                                 lastsourceline,
76                                                 element,
77                                                 pos,
78                                                 sourceLine);
79         String JavaDoc outputString = null;
80         if (indicateBranches) {
81             String JavaDoc branchIndicator = getBranchIndicatorString(element);
82             outputParams.add(branchIndicator);
83             assert outputParams.size() == 5; // make sure everything is in the list
84
outputString = "[{0}(PC):{1}(Source)]\t| {2:45}| {4:9}| {3}"; //$NON-NLS-1$
85
} else if (showPositions) {
86             assert outputParams.size() == 4; // make sure everything is in the list
87
outputString = "[{0}(PC):{1}(Source)]\t| {2:35}| {3}"; //$NON-NLS-1$
88
} else {
89             outputString = "{0}: {2}"; //$NON-NLS-1$
90
// outputString = "\"{0}: {2}\",";
91
}
92         String JavaDoc output = StringFormatter.format(
93                 outputString,
94                 outputParams.toArray(new String JavaDoc[outputParams.size()])
95                 );
96         return output;
97     }
98
99     /**
100      * @param element
101      */

102     private static String JavaDoc getBranchIndicatorString(InstructionHandle element) {
103         String JavaDoc branchIndicator = ""; //$NON-NLS-1$
104
if (element.getInstruction() instanceof BranchInstruction) {
105             branchIndicator = "branch"; //$NON-NLS-1$
106
} else if (element.getInstruction() instanceof ReturnInstruction) {
107             branchIndicator = "return"; //$NON-NLS-1$
108
}
109         return branchIndicator;
110     }
111
112     /**
113      * @param sourcecode
114      * @param code
115      * @param lastsourceline
116      * @param element
117      * @param pos
118      * @param sourceLine
119      */

120     private static List createOutputParams(SafeStringArray sourcecode,
121             Code code, int lastsourceline, InstructionHandle element,
122             int pos, int sourceLine) {
123         List outputParams = new ArrayList();
124         outputParams.add("" + pos); //$NON-NLS-1$
125
outputParams.add("" + sourceLine); //$NON-NLS-1$
126
outputParams.add(element.getInstruction().toString(
127                 code.getConstantPool()));
128         if (sourceLine == lastsourceline) {
129             outputParams.add(""); //$NON-NLS-1$
130
} else {
131             outputParams.add(sourcecode.getString(sourceLine - 1).trim());
132         }
133         return outputParams;
134     }
135
136     /**
137      *
138      * @param lineNumbers
139      * @param pos
140      * @return returns the line number in the source code that the instruction
141      * pointed to by <code>pos</code> is part of.
142      */

143     public static int getCorrespondingSourceLine(LineNumber[] lineNumbers, int pos) {
144         if (lineNumbers != null && lineNumbers.length > 0) {
145             int i = 0;
146             LineNumber largestSmallerNumber = null;
147             while (i < lineNumbers.length && lineNumbers[i].getStartPC() <= pos) {
148                 largestSmallerNumber = lineNumbers[i];
149                 i++;
150             }
151             if (largestSmallerNumber != null) {
152                 return largestSmallerNumber.getLineNumber();
153             }
154         }
155         return Integer.MIN_VALUE;
156     }
157
158     /**
159      * tries to open the source file to the corresponding JavaClass.
160      * assumes that the sources lie in directory "./src"
161      * @return returns a string array that contains the contents of the source
162      * class if the source class could be found. otherwise returns a string
163      * array with empty strings with 1.2 times as many entries as the largest
164      * line number could be found.
165      */

166     public static String JavaDoc[] openSource(JavaClass javaClass) {
167         String JavaDoc javaPath = javaClass.getPackageName().replaceAll("\\.", //$NON-NLS-1$
168
File.separator);
169         String JavaDoc javaSource = "src" + File.separator+ javaPath + File.separator //$NON-NLS-1$
170
+ javaClass.getSourceFileName();
171         
172         File file = new File(javaSource);
173         List lineList = new LinkedList();
174         LineNumberReader reader = null;
175         try {
176             reader = new LineNumberReader(new FileReader(file));
177         } catch (FileNotFoundException e) {
178             Logger.getInstance().info("File " + javaSource + " could not be found"); //$NON-NLS-1$ //$NON-NLS-2$
179
return generateErrorResult(javaClass);
180         }
181         String JavaDoc line = null;
182         try {
183             while ((line = reader.readLine()) != null) {
184                 lineList.add(line);
185             }
186         } catch (IOException e1) {
187             e1.printStackTrace();
188         }
189         return (String JavaDoc[]) lineList.toArray(new String JavaDoc[lineList.size()]);
190     }
191
192     /**
193      * for internal use only. Generates the error result for @link{openSource}.
194      * @param javaClass
195      */

196     private static String JavaDoc[] generateErrorResult(JavaClass javaClass) {
197         Method[] methods = javaClass.getMethods();
198         int maxLineNumber = 0;
199         for (int i = 0; i < methods.length; i++) {
200             LineNumberTable table = methods[i].getLineNumberTable();
201             if (table != null) {
202                 LineNumber[] linenumbers = table.getLineNumberTable();
203                 for (int j = 0; j < linenumbers.length; j++) {
204                     if (linenumbers[j] != null &&
205                             linenumbers[j].getLineNumber() > maxLineNumber) {
206                         maxLineNumber = linenumbers[j].getLineNumber();
207                     }
208                 }
209             }
210         }
211         String JavaDoc[] result = new String JavaDoc[maxLineNumber * 2];
212         for (int i = 0; i < result.length; i++) {
213             result[i] = "Source for " + javaClass.getClassName() + " could not be found"; //$NON-NLS-1$ //$NON-NLS-2$
214
}
215         return result;
216     }
217
218     public static void printByteCode(PrintStream out, String JavaDoc id, Code code, boolean indicateBranches, boolean showPositions) {
219         if (id != null) {
220             out.println(id);
221         }
222         if (code == null || code.getLineNumberTable() == null) {
223             return;
224         }
225         LineNumber[] lineNumbers = code.getLineNumberTable().getLineNumberTable();
226         InstructionList bytecode = new InstructionList(code.getCode());
227         bytecode.setPositions();
228         int lastsourceline = Integer.MIN_VALUE;
229
230         for (Iterator iter = bytecode.iterator(); iter.hasNext();) {
231             InstructionHandle element = (InstructionHandle) iter.next();
232             int pos = element.getPosition();
233             int sourceLine = getCorrespondingSourceLine(lineNumbers, pos);
234             if (lastsourceline != sourceLine && showPositions) {
235                 out.println("-------------------------------------------------------------------------------------------------"); //$NON-NLS-1$
236
}
237             String JavaDoc output = createOutputLine(indicateBranches,
238                                                 showPositions,
239                                                 sourcecode,
240                                                 code,
241                                                 lastsourceline,
242                                                 element,
243                                                 pos,
244                                                 sourceLine);
245             lastsourceline = sourceLine;
246             out.println(output);
247         }
248     }
249     
250     public static String JavaDoc[] printToStringArray(Code code) {
251         ByteCodePrinterThread t = new ByteCodePrinterThread(code);
252         BufferedReader reader = t.getReader();
253         t.start();
254         String JavaDoc line;
255         List lines = new ArrayList();
256         try {
257             while ((line = reader.readLine()) != null) {
258                 lines.add(line);
259             }
260         } catch (IOException e) {
261             e.printStackTrace();
262         }
263         return (String JavaDoc[]) lines.toArray(new String JavaDoc[lines.size()]);
264     }
265 }
Popular Tags