1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /*
   6  * Licensed to the Apache Software Foundation (ASF) under one or more
   7  * contributor license agreements.  See the NOTICE file distributed with
   8  * this work for additional information regarding copyright ownership.
   9  * The ASF licenses this file to You under the Apache License, Version 2.0
  10  * (the "License"); you may not use this file except in compliance with
  11  * the License.  You may obtain a copy of the License at
  12  *
  13  *      http://www.apache.org/licenses/LICENSE-2.0
  14  *
  15  * Unless required by applicable law or agreed to in writing, software
  16  * distributed under the License is distributed on an "AS IS" BASIS,
  17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18  * See the License for the specific language governing permissions and
  19  * limitations under the License.
  20  */
  21 
  22 package com.sun.org.apache.bcel.internal.util;
  23 
  24 import java.io.FileOutputStream;
  25 import java.io.IOException;
  26 import java.io.PrintWriter;
  27 
  28 import com.sun.org.apache.bcel.internal.Const;
  29 import com.sun.org.apache.bcel.internal.classfile.Attribute;
  30 import com.sun.org.apache.bcel.internal.classfile.Code;
  31 import com.sun.org.apache.bcel.internal.classfile.CodeException;
  32 import com.sun.org.apache.bcel.internal.classfile.ConstantPool;
  33 import com.sun.org.apache.bcel.internal.classfile.ConstantUtf8;
  34 import com.sun.org.apache.bcel.internal.classfile.ConstantValue;
  35 import com.sun.org.apache.bcel.internal.classfile.ExceptionTable;
  36 import com.sun.org.apache.bcel.internal.classfile.InnerClass;
  37 import com.sun.org.apache.bcel.internal.classfile.InnerClasses;
  38 import com.sun.org.apache.bcel.internal.classfile.LineNumber;
  39 import com.sun.org.apache.bcel.internal.classfile.LineNumberTable;
  40 import com.sun.org.apache.bcel.internal.classfile.LocalVariable;
  41 import com.sun.org.apache.bcel.internal.classfile.LocalVariableTable;
  42 import com.sun.org.apache.bcel.internal.classfile.SourceFile;
  43 import com.sun.org.apache.bcel.internal.classfile.Utility;
  44 
  45 /**
  46  * Convert found attributes into HTML file.
  47  *
  48  * @version $Id: AttributeHTML.java 1749603 2016-06-21 20:50:19Z ggregory $
  49  *
  50  */
  51 final class AttributeHTML {
  52 
  53     private final String class_name; // name of current class
  54     private final PrintWriter file; // file to write to
  55     private int attr_count = 0;
  56     private final ConstantHTML constant_html;
  57     private final ConstantPool constant_pool;
  58 
  59 
  60     AttributeHTML(final String dir, final String class_name, final ConstantPool constant_pool,
  61             final ConstantHTML constant_html) throws IOException {
  62         this.class_name = class_name;
  63         this.constant_pool = constant_pool;
  64         this.constant_html = constant_html;
  65         file = new PrintWriter(new FileOutputStream(dir + class_name + "_attributes.html"));
  66         file.println("<HTML><BODY BGCOLOR=\"#C0C0C0\"><TABLE BORDER=0>");
  67     }
  68 
  69 
  70     private String codeLink( final int link, final int method_number ) {
  71         return "<A HREF=\"" + class_name + "_code.html#code" + method_number + "@" + link
  72                 + "\" TARGET=Code>" + link + "</A>";
  73     }
  74 
  75 
  76     final void close() {
  77         file.println("</TABLE></BODY></HTML>");
  78         file.close();
  79     }
  80 
  81 
  82     final void writeAttribute( final Attribute attribute, final String anchor ) {
  83         writeAttribute(attribute, anchor, 0);
  84     }
  85 
  86 
  87     final void writeAttribute( final Attribute attribute, final String anchor, final int method_number ) {
  88         final byte tag = attribute.getTag();
  89         int index;
  90         if (tag == Const.ATTR_UNKNOWN) {
  91             return;
  92         }
  93         attr_count++; // Increment number of attributes found so far
  94         if (attr_count % 2 == 0) {
  95             file.print("<TR BGCOLOR=\"#C0C0C0\"><TD>");
  96         } else {
  97             file.print("<TR BGCOLOR=\"#A0A0A0\"><TD>");
  98         }
  99         file.println("<H4><A NAME=\"" + anchor + "\">" + attr_count + " " + Const.getAttributeName(tag)
 100                 + "</A></H4>");
 101         /* Handle different attributes
 102          */
 103         switch (tag) {
 104             case Const.ATTR_CODE:
 105                 final Code c = (Code) attribute;
 106                 // Some directly printable values
 107                 file.print("<UL><LI>Maximum stack size = " + c.getMaxStack()
 108                         + "</LI>\n<LI>Number of local variables = " + c.getMaxLocals()
 109                         + "</LI>\n<LI><A HREF=\"" + class_name + "_code.html#method"
 110                         + method_number + "\" TARGET=Code>Byte code</A></LI></UL>\n");
 111                 // Get handled exceptions and list them
 112                 final CodeException[] ce = c.getExceptionTable();
 113                 final int len = ce.length;
 114                 if (len > 0) {
 115                     file.print("<P><B>Exceptions handled</B><UL>");
 116                     for (final CodeException cex : ce) {
 117                         final int catch_type = cex.getCatchType(); // Index in constant pool
 118                         file.print("<LI>");
 119                         if (catch_type != 0) {
 120                             file.print(constant_html.referenceConstant(catch_type)); // Create Link to _cp.html
 121                         } else {
 122                             file.print("Any Exception");
 123                         }
 124                         file.print("<BR>(Ranging from lines "
 125                                 + codeLink(cex.getStartPC(), method_number) + " to "
 126                                 + codeLink(cex.getEndPC(), method_number) + ", handled at line "
 127                                 + codeLink(cex.getHandlerPC(), method_number) + ")</LI>");
 128                     }
 129                     file.print("</UL>");
 130                 }
 131                 break;
 132             case Const.ATTR_CONSTANT_VALUE:
 133                 index = ((ConstantValue) attribute).getConstantValueIndex();
 134                 // Reference _cp.html
 135                 file.print("<UL><LI><A HREF=\"" + class_name + "_cp.html#cp" + index
 136                         + "\" TARGET=\"ConstantPool\">Constant value index(" + index
 137                         + ")</A></UL>\n");
 138                 break;
 139             case Const.ATTR_SOURCE_FILE:
 140                 index = ((SourceFile) attribute).getSourceFileIndex();
 141                 // Reference _cp.html
 142                 file.print("<UL><LI><A HREF=\"" + class_name + "_cp.html#cp" + index
 143                         + "\" TARGET=\"ConstantPool\">Source file index(" + index + ")</A></UL>\n");
 144                 break;
 145             case Const.ATTR_EXCEPTIONS:
 146                 // List thrown exceptions
 147                 final int[] indices = ((ExceptionTable) attribute).getExceptionIndexTable();
 148                 file.print("<UL>");
 149                 for (final int indice : indices) {
 150                     file.print("<LI><A HREF=\"" + class_name + "_cp.html#cp" + indice
 151                             + "\" TARGET=\"ConstantPool\">Exception class index(" + indice
 152                             + ")</A>\n");
 153                 }
 154                 file.print("</UL>\n");
 155                 break;
 156             case Const.ATTR_LINE_NUMBER_TABLE:
 157                 final LineNumber[] line_numbers = ((LineNumberTable) attribute).getLineNumberTable();
 158                 // List line number pairs
 159                 file.print("<P>");
 160                 for (int i = 0; i < line_numbers.length; i++) {
 161                     file.print("(" + line_numbers[i].getStartPC() + ",&nbsp;"
 162                             + line_numbers[i].getLineNumber() + ")");
 163                     if (i < line_numbers.length - 1) {
 164                         file.print(", "); // breakable
 165                     }
 166                 }
 167                 break;
 168             case Const.ATTR_LOCAL_VARIABLE_TABLE:
 169                 final LocalVariable[] vars = ((LocalVariableTable) attribute).getLocalVariableTable();
 170                 // List name, range and type
 171                 file.print("<UL>");
 172                 for (final LocalVariable var : vars) {
 173                     index = var.getSignatureIndex();
 174                     String signature = ((ConstantUtf8) constant_pool.getConstant(index,
 175                             Const.CONSTANT_Utf8)).getBytes();
 176                     signature = Utility.signatureToString(signature, false);
 177                     final int start = var.getStartPC();
 178                     final int end = start + var.getLength();
 179                     file.println("<LI>" + Class2HTML.referenceType(signature) + "&nbsp;<B>"
 180                             + var.getName() + "</B> in slot %" + var.getIndex()
 181                             + "<BR>Valid from lines " + "<A HREF=\"" + class_name
 182                             + "_code.html#code" + method_number + "@" + start + "\" TARGET=Code>"
 183                             + start + "</A> to " + "<A HREF=\"" + class_name + "_code.html#code"
 184                             + method_number + "@" + end + "\" TARGET=Code>" + end + "</A></LI>");
 185                 }
 186                 file.print("</UL>\n");
 187                 break;
 188             case Const.ATTR_INNER_CLASSES:
 189                 final InnerClass[] classes = ((InnerClasses) attribute).getInnerClasses();
 190                 // List inner classes
 191                 file.print("<UL>");
 192                 for (final InnerClass classe : classes) {
 193                     String name;
 194                     String access;
 195                     index = classe.getInnerNameIndex();
 196                     if (index > 0) {
 197                         name = ((ConstantUtf8) constant_pool.getConstant(index, Const.CONSTANT_Utf8))
 198                                 .getBytes();
 199                     } else {
 200                         name = "&lt;anonymous&gt;";
 201                     }
 202                     access = Utility.accessToString(classe.getInnerAccessFlags());
 203                     file.print("<LI><FONT COLOR=\"#FF0000\">" + access + "</FONT> "
 204                             + constant_html.referenceConstant(classe.getInnerClassIndex())
 205                             + " in&nbsp;class "
 206                             + constant_html.referenceConstant(classe.getOuterClassIndex())
 207                             + " named " + name + "</LI>\n");
 208                 }
 209                 file.print("</UL>\n");
 210                 break;
 211             default: // Such as Unknown attribute or Deprecated
 212                 file.print("<P>" + attribute);
 213         }
 214         file.println("</TD></TR>");
 215         file.flush();
 216     }
 217 }