AttributeHTML.java

  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. package org.apache.bcel.util;

  18. import java.io.Closeable;
  19. import java.io.FileNotFoundException;
  20. import java.io.PrintWriter;
  21. import java.io.UnsupportedEncodingException;
  22. import java.nio.charset.Charset;

  23. import org.apache.bcel.Const;
  24. import org.apache.bcel.classfile.Attribute;
  25. import org.apache.bcel.classfile.Code;
  26. import org.apache.bcel.classfile.CodeException;
  27. import org.apache.bcel.classfile.ConstantPool;
  28. import org.apache.bcel.classfile.ConstantValue;
  29. import org.apache.bcel.classfile.ExceptionTable;
  30. import org.apache.bcel.classfile.InnerClass;
  31. import org.apache.bcel.classfile.InnerClasses;
  32. import org.apache.bcel.classfile.LineNumber;
  33. import org.apache.bcel.classfile.LineNumberTable;
  34. import org.apache.bcel.classfile.LocalVariableTable;
  35. import org.apache.bcel.classfile.SourceFile;
  36. import org.apache.bcel.classfile.Utility;

  37. /**
  38.  * Convert found attributes into HTML file.
  39.  */
  40. final class AttributeHTML implements Closeable {

  41.     private final String className; // name of current class
  42.     private final PrintWriter printWriter; // file to write to
  43.     private int attrCount;
  44.     private final ConstantHTML constantHtml;
  45.     private final ConstantPool constantPool;

  46.     AttributeHTML(final String dir, final String className, final ConstantPool constantPool, final ConstantHTML constantHtml, final Charset charset)
  47.         throws FileNotFoundException, UnsupportedEncodingException {
  48.         this.className = className;
  49.         this.constantPool = constantPool;
  50.         this.constantHtml = constantHtml;
  51.         printWriter = new PrintWriter(dir + className + "_attributes.html", charset.name());
  52.         printWriter.print("<HTML><head><meta charset=\"");
  53.         printWriter.print(charset.name());
  54.         printWriter.println("\"></head>");
  55.         printWriter.println("<BODY BGCOLOR=\"#C0C0C0\"><TABLE BORDER=0>");
  56.     }

  57.     @Override
  58.     public void close() {
  59.         printWriter.println("</TABLE></BODY></HTML>");
  60.         printWriter.close();
  61.     }

  62.     private String codeLink(final int link, final int methodNumber) {
  63.         return "<A HREF=\"" + className + "_code.html#code" + methodNumber + "@" + link + "\" TARGET=Code>" + link + "</A>";
  64.     }

  65.     void writeAttribute(final Attribute attribute, final String anchor) {
  66.         writeAttribute(attribute, anchor, 0);
  67.     }

  68.     void writeAttribute(final Attribute attribute, final String anchor, final int methodNumber) {
  69.         final byte tag = attribute.getTag();
  70.         int index;
  71.         if (tag == Const.ATTR_UNKNOWN) {
  72.             return;
  73.         }
  74.         attrCount++; // Increment number of attributes found so far
  75.         if (attrCount % 2 == 0) {
  76.             printWriter.print("<TR BGCOLOR=\"#C0C0C0\"><TD>");
  77.         } else {
  78.             printWriter.print("<TR BGCOLOR=\"#A0A0A0\"><TD>");
  79.         }
  80.         printWriter.println("<H4><A NAME=\"" + anchor + "\">" + attrCount + " " + Const.getAttributeName(tag) + "</A></H4>");
  81.         /*
  82.          * Handle different attributes
  83.          */
  84.         switch (tag) {
  85.         case Const.ATTR_CODE:
  86.             final Code c = (Code) attribute;
  87.             // Some directly printable values
  88.             printWriter.print("<UL><LI>Maximum stack size = " + c.getMaxStack() + "</LI>\n<LI>Number of local variables = " + c.getMaxLocals()
  89.                 + "</LI>\n<LI><A HREF=\"" + className + "_code.html#method" + methodNumber + "\" TARGET=Code>Byte code</A></LI></UL>\n");
  90.             // Get handled exceptions and list them
  91.             final CodeException[] ce = c.getExceptionTable();
  92.             final int len = ce.length;
  93.             if (len > 0) {
  94.                 printWriter.print("<P><B>Exceptions handled</B><UL>");
  95.                 for (final CodeException cex : ce) {
  96.                     final int catchType = cex.getCatchType(); // Index in constant pool
  97.                     printWriter.print("<LI>");
  98.                     if (catchType != 0) {
  99.                         printWriter.print(constantHtml.referenceConstant(catchType)); // Create Link to _cp.html
  100.                     } else {
  101.                         printWriter.print("Any Exception");
  102.                     }
  103.                     printWriter.print("<BR>(Ranging from lines " + codeLink(cex.getStartPC(), methodNumber) + " to " + codeLink(cex.getEndPC(), methodNumber)
  104.                         + ", handled at line " + codeLink(cex.getHandlerPC(), methodNumber) + ")</LI>");
  105.                 }
  106.                 printWriter.print("</UL>");
  107.             }
  108.             break;
  109.         case Const.ATTR_CONSTANT_VALUE:
  110.             index = ((ConstantValue) attribute).getConstantValueIndex();
  111.             // Reference _cp.html
  112.             printWriter
  113.                 .print("<UL><LI><A HREF=\"" + className + "_cp.html#cp" + index + "\" TARGET=\"ConstantPool\">Constant value index(" + index + ")</A></UL>\n");
  114.             break;
  115.         case Const.ATTR_SOURCE_FILE:
  116.             index = ((SourceFile) attribute).getSourceFileIndex();
  117.             // Reference _cp.html
  118.             printWriter
  119.                 .print("<UL><LI><A HREF=\"" + className + "_cp.html#cp" + index + "\" TARGET=\"ConstantPool\">Source file index(" + index + ")</A></UL>\n");
  120.             break;
  121.         case Const.ATTR_EXCEPTIONS:
  122.             // List thrown exceptions
  123.             final int[] indices = ((ExceptionTable) attribute).getExceptionIndexTable();
  124.             printWriter.print("<UL>");
  125.             for (final int indice : indices) {
  126.                 printWriter
  127.                     .print("<LI><A HREF=\"" + className + "_cp.html#cp" + indice + "\" TARGET=\"ConstantPool\">Exception class index(" + indice + ")</A>\n");
  128.             }
  129.             printWriter.print("</UL>\n");
  130.             break;
  131.         case Const.ATTR_LINE_NUMBER_TABLE:
  132.             final LineNumber[] lineNumbers = ((LineNumberTable) attribute).getLineNumberTable();
  133.             // List line number pairs
  134.             printWriter.print("<P>");
  135.             for (int i = 0; i < lineNumbers.length; i++) {
  136.                 printWriter.print("(" + lineNumbers[i].getStartPC() + ",&nbsp;" + lineNumbers[i].getLineNumber() + ")");
  137.                 if (i < lineNumbers.length - 1) {
  138.                     printWriter.print(", "); // breakable
  139.                 }
  140.             }
  141.             break;
  142.         case Const.ATTR_LOCAL_VARIABLE_TABLE:
  143.             // List name, range and type
  144.             printWriter.print("<UL>");
  145.             ((LocalVariableTable) attribute).forEach(var -> {
  146.                 final int sigIdx = var.getSignatureIndex();
  147.                 String signature = constantPool.getConstantUtf8(sigIdx).getBytes();
  148.                 signature = Utility.signatureToString(signature, false);
  149.                 final int start = var.getStartPC();
  150.                 final int end = start + var.getLength();
  151.                 printWriter.println("<LI>" + Class2HTML.referenceType(signature) + "&nbsp;<B>" + var.getName() + "</B> in slot %" + var.getIndex()
  152.                     + "<BR>Valid from lines " + "<A HREF=\"" + className + "_code.html#code" + methodNumber + "@" + start + "\" TARGET=Code>" + start
  153.                     + "</A> to " + "<A HREF=\"" + className + "_code.html#code" + methodNumber + "@" + end + "\" TARGET=Code>" + end + "</A></LI>");
  154.             });
  155.             printWriter.print("</UL>\n");
  156.             break;
  157.         case Const.ATTR_INNER_CLASSES:
  158.             // List inner classes
  159.             printWriter.print("<UL>");
  160.             for (final InnerClass clazz : ((InnerClasses) attribute).getInnerClasses()) {
  161.                 final String name;
  162.                 final String access;
  163.                 index = clazz.getInnerNameIndex();
  164.                 if (index > 0) {
  165.                     name = constantPool.getConstantUtf8(index).getBytes();
  166.                 } else {
  167.                     name = "&lt;anonymous&gt;";
  168.                 }
  169.                 access = Utility.accessToString(clazz.getInnerAccessFlags());
  170.                 printWriter.print("<LI><FONT COLOR=\"#FF0000\">" + access + "</FONT> " + constantHtml.referenceConstant(clazz.getInnerClassIndex())
  171.                     + " in&nbsp;class " + constantHtml.referenceConstant(clazz.getOuterClassIndex()) + " named " + name + "</LI>\n");
  172.             }
  173.             printWriter.print("</UL>\n");
  174.             break;
  175.         default: // Such as Unknown attribute or Deprecated
  176.             printWriter.print("<P>" + attribute);
  177.         }
  178.         printWriter.println("</TD></TR>");
  179.         printWriter.flush();
  180.     }
  181. }