View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   https://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
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   * Convert found attributes into HTML file.
44   */
45  final class AttributeHTML implements Closeable {
46  
47      private final String className; // name of current class
48      private final PrintWriter printWriter; // file to write to
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++; // Increment number of attributes found so far
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           * Handle different attributes
94           */
95          switch (tag) {
96          case Const.ATTR_CODE:
97              final Code c = (Code) attribute;
98              // Some directly printable values
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             // Get handled exceptions and list them
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(); // Index in constant pool
108                     printWriter.print("<LI>");
109                     if (catchType != 0) {
110                         printWriter.print(constantHtml.referenceConstant(catchType)); // Create Link to _cp.html
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             // Reference _cp.html
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             // Reference _cp.html
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             // List thrown exceptions
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             // List line number pairs
145             printWriter.print("<P>");
146             for (int i = 0; i < lineNumbers.length; i++) {
147                 printWriter.print("(" + lineNumbers[i].getStartPC() + ",&nbsp;" + lineNumbers[i].getLineNumber() + ")");
148                 if (i < lineNumbers.length - 1) {
149                     printWriter.print(", "); // breakable
150                 }
151             }
152             break;
153         case Const.ATTR_LOCAL_VARIABLE_TABLE:
154             // List name, range and type
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) + "&nbsp;<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             // List inner classes
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 = "&lt;anonymous&gt;";
179                 }
180                 access = Utility.accessToString(clazz.getInnerAccessFlags());
181                 printWriter.print("<LI><FONT COLOR=\"#FF0000\">" + access + "</FONT> " + constantHtml.referenceConstant(clazz.getInnerClassIndex())
182                     + " in&nbsp;class " + constantHtml.referenceConstant(clazz.getOuterClassIndex()) + " named " + name + "</LI>\n");
183             }
184             printWriter.print("</UL>\n");
185             break;
186         default: // Such as Unknown attribute or Deprecated
187             printWriter.print("<P>" + attribute);
188         }
189         printWriter.println("</TD></TR>");
190         printWriter.flush();
191     }
192 }