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  */
18 package org.apache.bcel.util;
19 
20 import java.io.FileOutputStream;
21 import java.io.IOException;
22 import java.io.PrintWriter;
23 
24 import org.apache.bcel.Const;
25 import org.apache.bcel.classfile.Attribute;
26 import org.apache.bcel.classfile.Code;
27 import org.apache.bcel.classfile.CodeException;
28 import org.apache.bcel.classfile.ConstantPool;
29 import org.apache.bcel.classfile.ConstantUtf8;
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.LocalVariable;
37 import org.apache.bcel.classfile.LocalVariableTable;
38 import org.apache.bcel.classfile.SourceFile;
39 import org.apache.bcel.classfile.Utility;
40 
41 /**
42  * Convert found attributes into HTML file.
43  *
44  * @version $Id$
45  *
46  */
47 final class AttributeHTML {
48 
49     private final String class_name; // name of current class
50     private final PrintWriter file; // file to write to
51     private int attr_count = 0;
52     private final ConstantHTML constant_html;
53     private final ConstantPool constant_pool;
54 
55 
AttributeHTML(final String dir, final String class_name, final ConstantPool constant_pool, final ConstantHTML constant_html)56     AttributeHTML(final String dir, final String class_name, final ConstantPool constant_pool,
57             final ConstantHTML constant_html) throws IOException {
58         this.class_name = class_name;
59         this.constant_pool = constant_pool;
60         this.constant_html = constant_html;
61         file = new PrintWriter(new FileOutputStream(dir + class_name + "_attributes.html"));
62         file.println("<HTML><BODY BGCOLOR=\"#C0C0C0\"><TABLE BORDER=0>");
63     }
64 
65 
codeLink( final int link, final int method_number )66     private String codeLink( final int link, final int method_number ) {
67         return "<A HREF=\"" + class_name + "_code.html#code" + method_number + "@" + link
68                 + "\" TARGET=Code>" + link + "</A>";
69     }
70 
71 
close()72     final void close() {
73         file.println("</TABLE></BODY></HTML>");
74         file.close();
75     }
76 
77 
writeAttribute( final Attribute attribute, final String anchor )78     final void writeAttribute( final Attribute attribute, final String anchor ) {
79         writeAttribute(attribute, anchor, 0);
80     }
81 
82 
writeAttribute( final Attribute attribute, final String anchor, final int method_number )83     final void writeAttribute( final Attribute attribute, final String anchor, final int method_number ) {
84         final byte tag = attribute.getTag();
85         int index;
86         if (tag == Const.ATTR_UNKNOWN) {
87             return;
88         }
89         attr_count++; // Increment number of attributes found so far
90         if (attr_count % 2 == 0) {
91             file.print("<TR BGCOLOR=\"#C0C0C0\"><TD>");
92         } else {
93             file.print("<TR BGCOLOR=\"#A0A0A0\"><TD>");
94         }
95         file.println("<H4><A NAME=\"" + anchor + "\">" + attr_count + " " + Const.getAttributeName(tag)
96                 + "</A></H4>");
97         /* Handle different attributes
98          */
99         switch (tag) {
100             case Const.ATTR_CODE:
101                 final Code c = (Code) attribute;
102                 // Some directly printable values
103                 file.print("<UL><LI>Maximum stack size = " + c.getMaxStack()
104                         + "</LI>\n<LI>Number of local variables = " + c.getMaxLocals()
105                         + "</LI>\n<LI><A HREF=\"" + class_name + "_code.html#method"
106                         + method_number + "\" TARGET=Code>Byte code</A></LI></UL>\n");
107                 // Get handled exceptions and list them
108                 final CodeException[] ce = c.getExceptionTable();
109                 final int len = ce.length;
110                 if (len > 0) {
111                     file.print("<P><B>Exceptions handled</B><UL>");
112                     for (final CodeException cex : ce) {
113                         final int catch_type = cex.getCatchType(); // Index in constant pool
114                         file.print("<LI>");
115                         if (catch_type != 0) {
116                             file.print(constant_html.referenceConstant(catch_type)); // Create Link to _cp.html
117                         } else {
118                             file.print("Any Exception");
119                         }
120                         file.print("<BR>(Ranging from lines "
121                                 + codeLink(cex.getStartPC(), method_number) + " to "
122                                 + codeLink(cex.getEndPC(), method_number) + ", handled at line "
123                                 + codeLink(cex.getHandlerPC(), method_number) + ")</LI>");
124                     }
125                     file.print("</UL>");
126                 }
127                 break;
128             case Const.ATTR_CONSTANT_VALUE:
129                 index = ((ConstantValue) attribute).getConstantValueIndex();
130                 // Reference _cp.html
131                 file.print("<UL><LI><A HREF=\"" + class_name + "_cp.html#cp" + index
132                         + "\" TARGET=\"ConstantPool\">Constant value index(" + index
133                         + ")</A></UL>\n");
134                 break;
135             case Const.ATTR_SOURCE_FILE:
136                 index = ((SourceFile) attribute).getSourceFileIndex();
137                 // Reference _cp.html
138                 file.print("<UL><LI><A HREF=\"" + class_name + "_cp.html#cp" + index
139                         + "\" TARGET=\"ConstantPool\">Source file index(" + index + ")</A></UL>\n");
140                 break;
141             case Const.ATTR_EXCEPTIONS:
142                 // List thrown exceptions
143                 final int[] indices = ((ExceptionTable) attribute).getExceptionIndexTable();
144                 file.print("<UL>");
145                 for (final int indice : indices) {
146                     file.print("<LI><A HREF=\"" + class_name + "_cp.html#cp" + indice
147                             + "\" TARGET=\"ConstantPool\">Exception class index(" + indice
148                             + ")</A>\n");
149                 }
150                 file.print("</UL>\n");
151                 break;
152             case Const.ATTR_LINE_NUMBER_TABLE:
153                 final LineNumber[] line_numbers = ((LineNumberTable) attribute).getLineNumberTable();
154                 // List line number pairs
155                 file.print("<P>");
156                 for (int i = 0; i < line_numbers.length; i++) {
157                     file.print("(" + line_numbers[i].getStartPC() + ",&nbsp;"
158                             + line_numbers[i].getLineNumber() + ")");
159                     if (i < line_numbers.length - 1) {
160                         file.print(", "); // breakable
161                     }
162                 }
163                 break;
164             case Const.ATTR_LOCAL_VARIABLE_TABLE:
165                 final LocalVariable[] vars = ((LocalVariableTable) attribute).getLocalVariableTable();
166                 // List name, range and type
167                 file.print("<UL>");
168                 for (final LocalVariable var : vars) {
169                     index = var.getSignatureIndex();
170                     String signature = ((ConstantUtf8) constant_pool.getConstant(index,
171                             Const.CONSTANT_Utf8)).getBytes();
172                     signature = Utility.signatureToString(signature, false);
173                     final int start = var.getStartPC();
174                     final int end = start + var.getLength();
175                     file.println("<LI>" + Class2HTML.referenceType(signature) + "&nbsp;<B>"
176                             + var.getName() + "</B> in slot %" + var.getIndex()
177                             + "<BR>Valid from lines " + "<A HREF=\"" + class_name
178                             + "_code.html#code" + method_number + "@" + start + "\" TARGET=Code>"
179                             + start + "</A> to " + "<A HREF=\"" + class_name + "_code.html#code"
180                             + method_number + "@" + end + "\" TARGET=Code>" + end + "</A></LI>");
181                 }
182                 file.print("</UL>\n");
183                 break;
184             case Const.ATTR_INNER_CLASSES:
185                 final InnerClass[] classes = ((InnerClasses) attribute).getInnerClasses();
186                 // List inner classes
187                 file.print("<UL>");
188                 for (final InnerClass classe : classes) {
189                     String name;
190                     String access;
191                     index = classe.getInnerNameIndex();
192                     if (index > 0) {
193                         name = ((ConstantUtf8) constant_pool.getConstant(index, Const.CONSTANT_Utf8))
194                                 .getBytes();
195                     } else {
196                         name = "&lt;anonymous&gt;";
197                     }
198                     access = Utility.accessToString(classe.getInnerAccessFlags());
199                     file.print("<LI><FONT COLOR=\"#FF0000\">" + access + "</FONT> "
200                             + constant_html.referenceConstant(classe.getInnerClassIndex())
201                             + " in&nbsp;class "
202                             + constant_html.referenceConstant(classe.getOuterClassIndex())
203                             + " named " + name + "</LI>\n");
204                 }
205                 file.print("</UL>\n");
206                 break;
207             default: // Such as Unknown attribute or Deprecated
208                 file.print("<P>" + attribute);
209         }
210         file.println("</TD></TR>");
211         file.flush();
212     }
213 }
214