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.FileNotFoundException;
22  import java.io.PrintWriter;
23  import java.io.UnsupportedEncodingException;
24  import java.nio.charset.Charset;
25  
26  import org.apache.bcel.Const;
27  import org.apache.bcel.classfile.Constant;
28  import org.apache.bcel.classfile.ConstantClass;
29  import org.apache.bcel.classfile.ConstantFieldref;
30  import org.apache.bcel.classfile.ConstantInterfaceMethodref;
31  import org.apache.bcel.classfile.ConstantMethodref;
32  import org.apache.bcel.classfile.ConstantNameAndType;
33  import org.apache.bcel.classfile.ConstantPool;
34  import org.apache.bcel.classfile.ConstantString;
35  import org.apache.bcel.classfile.Method;
36  import org.apache.bcel.classfile.Utility;
37  
38  /**
39   * Convert constant pool into HTML file.
40   */
41  final class ConstantHTML {
42  
43      private final String className; // name of current class
44      private final String classPackage; // name of package
45      private final ConstantPool constantPool; // reference to constant pool
46      private final PrintWriter printWriter; // file to write to
47      private final String[] constantRef; // String to return for cp[i]
48      private final Constant[] constants; // The constants in the cp
49      private final Method[] methods;
50  
51      ConstantHTML(final String dir, final String className, final String classPackage, final Method[] methods, final ConstantPool constantPool,
52          final Charset charset) throws FileNotFoundException, UnsupportedEncodingException {
53          this.className = className;
54          this.classPackage = classPackage;
55          this.constantPool = constantPool;
56          this.methods = methods;
57          this.constants = constantPool.getConstantPool();
58          try (PrintWriter newPrintWriter = new PrintWriter(dir + className + "_cp.html", charset.name())) {
59              printWriter = newPrintWriter;
60              constantRef = new String[constants.length];
61              constantRef[0] = "<unknown>";
62              printWriter.print("<HTML><head><meta charset=\"");
63              printWriter.print(charset.name());
64              printWriter.println("\"></head>");
65              printWriter.println("<BODY BGCOLOR=\"#C0C0C0\"><TABLE BORDER=0>");
66              // Loop through constants, constants[0] is reserved
67              for (int i = 1; i < constants.length; i++) {
68                  if (i % 2 == 0) {
69                      printWriter.print("<TR BGCOLOR=\"#C0C0C0\"><TD>");
70                  } else {
71                      printWriter.print("<TR BGCOLOR=\"#A0A0A0\"><TD>");
72                  }
73                  if (constants[i] != null) {
74                      writeConstant(i);
75                  }
76                  printWriter.print("</TD></TR>\n");
77              }
78              printWriter.println("</TABLE></BODY></HTML>");
79          }
80      }
81  
82      private int getMethodNumber(final String str) {
83          for (int i = 0; i < methods.length; i++) {
84              final String cmp = methods[i].getName() + methods[i].getSignature();
85              if (cmp.equals(str)) {
86                  return i;
87              }
88          }
89          return -1;
90      }
91  
92      String referenceConstant(final int index) {
93          return constantRef[index];
94      }
95  
96      private void writeConstant(final int index) {
97          final byte tag = constants[index].getTag();
98          final int classIndex;
99          final int nameIndex;
100         final String ref;
101         // The header is always the same
102         printWriter.println("<H4> <A NAME=cp" + index + ">" + index + "</A> " + Const.getConstantName(tag) + "</H4>");
103         /*
104          * For every constant type get the needed parameters and print them appropriately
105          */
106         switch (tag) {
107         case Const.CONSTANT_InterfaceMethodref:
108         case Const.CONSTANT_Methodref:
109             // Get class_index and name_and_type_index, depending on type
110             if (tag == Const.CONSTANT_Methodref) {
111                 final ConstantMethodref c = constantPool.getConstant(index, Const.CONSTANT_Methodref, ConstantMethodref.class);
112                 classIndex = c.getClassIndex();
113                 nameIndex = c.getNameAndTypeIndex();
114             } else {
115                 final ConstantInterfaceMethodref c1 = constantPool.getConstant(index, Const.CONSTANT_InterfaceMethodref, ConstantInterfaceMethodref.class);
116                 classIndex = c1.getClassIndex();
117                 nameIndex = c1.getNameAndTypeIndex();
118             }
119             // Get method name and its class
120             final String methodName = constantPool.constantToString(nameIndex, Const.CONSTANT_NameAndType);
121             final String htmlMethodName = Class2HTML.toHTML(methodName);
122             // Partially compacted class name, i.e., / -> .
123             final String methodClass = constantPool.constantToString(classIndex, Const.CONSTANT_Class);
124             String shortMethodClass = Utility.compactClassName(methodClass); // I.e., remove java.lang.
125             shortMethodClass = Utility.compactClassName(shortMethodClass, classPackage + ".", true); // Remove class package prefix
126             // Get method signature
127             final ConstantNameAndType c2 = constantPool.getConstant(nameIndex, Const.CONSTANT_NameAndType, ConstantNameAndType.class);
128             final String signature = constantPool.constantToString(c2.getSignatureIndex(), Const.CONSTANT_Utf8);
129             // Get array of strings containing the argument types
130             final String[] args = Utility.methodSignatureArgumentTypes(signature, false);
131             // Get return type string
132             final String type = Utility.methodSignatureReturnType(signature, false);
133             final String retType = Class2HTML.referenceType(type);
134             final StringBuilder buf = new StringBuilder("(");
135             for (int i = 0; i < args.length; i++) {
136                 buf.append(Class2HTML.referenceType(args[i]));
137                 if (i < args.length - 1) {
138                     buf.append(",&nbsp;");
139                 }
140             }
141             buf.append(")");
142             final String argTypes = buf.toString();
143             if (methodClass.equals(className)) {
144                 ref = "<A HREF=\"" + className + "_code.html#method" + getMethodNumber(methodName + signature) + "\" TARGET=Code>" + htmlMethodName + "</A>";
145             } else {
146                 ref = "<A HREF=\"" + methodClass + ".html\" TARGET=_top>" + shortMethodClass + "</A>." + htmlMethodName;
147             }
148             constantRef[index] = retType + "&nbsp;<A HREF=\"" + className + "_cp.html#cp" + classIndex + "\" TARGET=Constants>" + shortMethodClass
149                 + "</A>.<A HREF=\"" + className + "_cp.html#cp" + index + "\" TARGET=ConstantPool>" + htmlMethodName + "</A>&nbsp;" + argTypes;
150             printWriter.println("<P><TT>" + retType + "&nbsp;" + ref + argTypes + "&nbsp;</TT>\n<UL><LI><A HREF=\"#cp" + classIndex + "\">Class index("
151                 + classIndex + ")</A>\n" + "<LI><A HREF=\"#cp" + nameIndex + "\">NameAndType index(" + nameIndex + ")</A></UL>");
152             break;
153         case Const.CONSTANT_Fieldref:
154             // Get class_index and name_and_type_index
155             final ConstantFieldref c3 = constantPool.getConstant(index, Const.CONSTANT_Fieldref, ConstantFieldref.class);
156             classIndex = c3.getClassIndex();
157             nameIndex = c3.getNameAndTypeIndex();
158             // Get method name and its class (compacted)
159             final String fieldClass = constantPool.constantToString(classIndex, Const.CONSTANT_Class);
160             String shortFieldClass = Utility.compactClassName(fieldClass); // I.e., remove java.lang.
161             shortFieldClass = Utility.compactClassName(shortFieldClass, classPackage + ".", true); // Remove class package prefix
162             final String fieldName = constantPool.constantToString(nameIndex, Const.CONSTANT_NameAndType);
163             if (fieldClass.equals(className)) {
164                 ref = "<A HREF=\"" + fieldClass + "_methods.html#field" + fieldName + "\" TARGET=Methods>" + fieldName + "</A>";
165             } else {
166                 ref = "<A HREF=\"" + fieldClass + ".html\" TARGET=_top>" + shortFieldClass + "</A>." + fieldName + "\n";
167             }
168             constantRef[index] = "<A HREF=\"" + className + "_cp.html#cp" + classIndex + "\" TARGET=Constants>" + shortFieldClass + "</A>.<A HREF=\""
169                 + className + "_cp.html#cp" + index + "\" TARGET=ConstantPool>" + fieldName + "</A>";
170             printWriter.println("<P><TT>" + ref + "</TT><BR>\n" + "<UL>" + "<LI><A HREF=\"#cp" + classIndex + "\">Class(" + classIndex + ")</A><BR>\n"
171                 + "<LI><A HREF=\"#cp" + nameIndex + "\">NameAndType(" + nameIndex + ")</A></UL>");
172             break;
173         case Const.CONSTANT_Class:
174             final ConstantClass c4 = constantPool.getConstant(index, Const.CONSTANT_Class, ConstantClass.class);
175             nameIndex = c4.getNameIndex();
176             final String className2 = constantPool.constantToString(index, tag); // / -> .
177             String shortClassName = Utility.compactClassName(className2); // I.e., remove java.lang.
178             shortClassName = Utility.compactClassName(shortClassName, classPackage + ".", true); // Remove class package prefix
179             ref = "<A HREF=\"" + className2 + ".html\" TARGET=_top>" + shortClassName + "</A>";
180             constantRef[index] = "<A HREF=\"" + className + "_cp.html#cp" + index + "\" TARGET=ConstantPool>" + shortClassName + "</A>";
181             printWriter.println("<P><TT>" + ref + "</TT><UL>" + "<LI><A HREF=\"#cp" + nameIndex + "\">Name index(" + nameIndex + ")</A></UL>\n");
182             break;
183         case Const.CONSTANT_String:
184             final ConstantString c5 = constantPool.getConstant(index, Const.CONSTANT_String, ConstantString.class);
185             nameIndex = c5.getStringIndex();
186             final String str = Class2HTML.toHTML(constantPool.constantToString(index, tag));
187             printWriter.println("<P><TT>" + str + "</TT><UL>" + "<LI><A HREF=\"#cp" + nameIndex + "\">Name index(" + nameIndex + ")</A></UL>\n");
188             break;
189         case Const.CONSTANT_NameAndType:
190             final ConstantNameAndType c6 = constantPool.getConstant(index, Const.CONSTANT_NameAndType, ConstantNameAndType.class);
191             nameIndex = c6.getNameIndex();
192             final int signatureIndex = c6.getSignatureIndex();
193             printWriter.println("<P><TT>" + Class2HTML.toHTML(constantPool.constantToString(index, tag)) + "</TT><UL>" + "<LI><A HREF=\"#cp" + nameIndex
194                 + "\">Name index(" + nameIndex + ")</A>\n" + "<LI><A HREF=\"#cp" + signatureIndex + "\">Signature index(" + signatureIndex + ")</A></UL>\n");
195             break;
196         default:
197             printWriter.println("<P><TT>" + Class2HTML.toHTML(constantPool.constantToString(index, tag)) + "</TT>\n");
198         } // switch
199     }
200 }