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