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