1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.bcel.util;
18
19 import java.io.Closeable;
20 import java.io.FileNotFoundException;
21 import java.io.PrintWriter;
22 import java.io.UnsupportedEncodingException;
23 import java.nio.charset.Charset;
24
25 import org.apache.bcel.Const;
26 import org.apache.bcel.classfile.Attribute;
27 import org.apache.bcel.classfile.Code;
28 import org.apache.bcel.classfile.CodeException;
29 import org.apache.bcel.classfile.ConstantPool;
30 import org.apache.bcel.classfile.ConstantValue;
31 import org.apache.bcel.classfile.ExceptionTable;
32 import org.apache.bcel.classfile.InnerClass;
33 import org.apache.bcel.classfile.InnerClasses;
34 import org.apache.bcel.classfile.LineNumber;
35 import org.apache.bcel.classfile.LineNumberTable;
36 import org.apache.bcel.classfile.LocalVariableTable;
37 import org.apache.bcel.classfile.SourceFile;
38 import org.apache.bcel.classfile.Utility;
39
40
41
42
43 final class AttributeHTML implements Closeable {
44
45 private final String className;
46 private final PrintWriter printWriter;
47 private int attrCount;
48 private final ConstantHTML constantHtml;
49 private final ConstantPool constantPool;
50
51 AttributeHTML(final String dir, final String className, final ConstantPool constantPool, final ConstantHTML constantHtml, final Charset charset)
52 throws FileNotFoundException, UnsupportedEncodingException {
53 this.className = className;
54 this.constantPool = constantPool;
55 this.constantHtml = constantHtml;
56 printWriter = new PrintWriter(dir + className + "_attributes.html", charset.name());
57 printWriter.print("<HTML><head><meta charset=\"");
58 printWriter.print(charset.name());
59 printWriter.println("\"></head>");
60 printWriter.println("<BODY BGCOLOR=\"#C0C0C0\"><TABLE BORDER=0>");
61 }
62
63 @Override
64 public void close() {
65 printWriter.println("</TABLE></BODY></HTML>");
66 printWriter.close();
67 }
68
69 private String codeLink(final int link, final int methodNumber) {
70 return "<A HREF=\"" + className + "_code.html#code" + methodNumber + "@" + link + "\" TARGET=Code>" + link + "</A>";
71 }
72
73 void writeAttribute(final Attribute attribute, final String anchor) {
74 writeAttribute(attribute, anchor, 0);
75 }
76
77 void writeAttribute(final Attribute attribute, final String anchor, final int methodNumber) {
78 final byte tag = attribute.getTag();
79 int index;
80 if (tag == Const.ATTR_UNKNOWN) {
81 return;
82 }
83 attrCount++;
84 if (attrCount % 2 == 0) {
85 printWriter.print("<TR BGCOLOR=\"#C0C0C0\"><TD>");
86 } else {
87 printWriter.print("<TR BGCOLOR=\"#A0A0A0\"><TD>");
88 }
89 printWriter.println("<H4><A NAME=\"" + anchor + "\">" + attrCount + " " + Const.getAttributeName(tag) + "</A></H4>");
90
91
92
93 switch (tag) {
94 case Const.ATTR_CODE:
95 final Code c = (Code) attribute;
96
97 printWriter.print("<UL><LI>Maximum stack size = " + c.getMaxStack() + "</LI>\n<LI>Number of local variables = " + c.getMaxLocals()
98 + "</LI>\n<LI><A HREF=\"" + className + "_code.html#method" + methodNumber + "\" TARGET=Code>Byte code</A></LI></UL>\n");
99
100 final CodeException[] ce = c.getExceptionTable();
101 final int len = ce.length;
102 if (len > 0) {
103 printWriter.print("<P><B>Exceptions handled</B><UL>");
104 for (final CodeException cex : ce) {
105 final int catchType = cex.getCatchType();
106 printWriter.print("<LI>");
107 if (catchType != 0) {
108 printWriter.print(constantHtml.referenceConstant(catchType));
109 } else {
110 printWriter.print("Any Exception");
111 }
112 printWriter.print("<BR>(Ranging from lines " + codeLink(cex.getStartPC(), methodNumber) + " to " + codeLink(cex.getEndPC(), methodNumber)
113 + ", handled at line " + codeLink(cex.getHandlerPC(), methodNumber) + ")</LI>");
114 }
115 printWriter.print("</UL>");
116 }
117 break;
118 case Const.ATTR_CONSTANT_VALUE:
119 index = ((ConstantValue) attribute).getConstantValueIndex();
120
121 printWriter
122 .print("<UL><LI><A HREF=\"" + className + "_cp.html#cp" + index + "\" TARGET=\"ConstantPool\">Constant value index(" + index + ")</A></UL>\n");
123 break;
124 case Const.ATTR_SOURCE_FILE:
125 index = ((SourceFile) attribute).getSourceFileIndex();
126
127 printWriter
128 .print("<UL><LI><A HREF=\"" + className + "_cp.html#cp" + index + "\" TARGET=\"ConstantPool\">Source file index(" + index + ")</A></UL>\n");
129 break;
130 case Const.ATTR_EXCEPTIONS:
131
132 final int[] indices = ((ExceptionTable) attribute).getExceptionIndexTable();
133 printWriter.print("<UL>");
134 for (final int indice : indices) {
135 printWriter
136 .print("<LI><A HREF=\"" + className + "_cp.html#cp" + indice + "\" TARGET=\"ConstantPool\">Exception class index(" + indice + ")</A>\n");
137 }
138 printWriter.print("</UL>\n");
139 break;
140 case Const.ATTR_LINE_NUMBER_TABLE:
141 final LineNumber[] lineNumbers = ((LineNumberTable) attribute).getLineNumberTable();
142
143 printWriter.print("<P>");
144 for (int i = 0; i < lineNumbers.length; i++) {
145 printWriter.print("(" + lineNumbers[i].getStartPC() + ", " + lineNumbers[i].getLineNumber() + ")");
146 if (i < lineNumbers.length - 1) {
147 printWriter.print(", ");
148 }
149 }
150 break;
151 case Const.ATTR_LOCAL_VARIABLE_TABLE:
152
153 printWriter.print("<UL>");
154 ((LocalVariableTable) attribute).forEach(var -> {
155 final int sigIdx = var.getSignatureIndex();
156 String signature = constantPool.getConstantUtf8(sigIdx).getBytes();
157 signature = Utility.signatureToString(signature, false);
158 final int start = var.getStartPC();
159 final int end = start + var.getLength();
160 printWriter.println("<LI>" + Class2HTML.referenceType(signature) + " <B>" + var.getName() + "</B> in slot %" + var.getIndex()
161 + "<BR>Valid from lines " + "<A HREF=\"" + className + "_code.html#code" + methodNumber + "@" + start + "\" TARGET=Code>" + start
162 + "</A> to " + "<A HREF=\"" + className + "_code.html#code" + methodNumber + "@" + end + "\" TARGET=Code>" + end + "</A></LI>");
163 });
164 printWriter.print("</UL>\n");
165 break;
166 case Const.ATTR_INNER_CLASSES:
167
168 printWriter.print("<UL>");
169 for (final InnerClass clazz : ((InnerClasses) attribute).getInnerClasses()) {
170 final String name;
171 final String access;
172 index = clazz.getInnerNameIndex();
173 if (index > 0) {
174 name = constantPool.getConstantUtf8(index).getBytes();
175 } else {
176 name = "<anonymous>";
177 }
178 access = Utility.accessToString(clazz.getInnerAccessFlags());
179 printWriter.print("<LI><FONT COLOR=\"#FF0000\">" + access + "</FONT> " + constantHtml.referenceConstant(clazz.getInnerClassIndex())
180 + " in class " + constantHtml.referenceConstant(clazz.getOuterClassIndex()) + " named " + name + "</LI>\n");
181 }
182 printWriter.print("</UL>\n");
183 break;
184 default:
185 printWriter.print("<P>" + attribute);
186 }
187 printWriter.println("</TD></TR>");
188 printWriter.flush();
189 }
190 }