1 package attrib4j.bcel;
2
3 import java.util.HashMap;
4 import java.util.Map;
5 import java.util.StringTokenizer;
6
7 import attrib4j.Log;
8
9 /***
10 * The signature of a method that is available from the BCEL library uses
11 * descriptors as defined in Section 4.3 of the Java Virtual Machine
12 * specificaiton. Javadoc and Java do not use signatures in this same format.
13 * This class converts the Javadoc/Java signature format to that used by
14 * the JVM spec.
15 * To summarize the descriptors
16 * <code>
17 * A method descriptor represents the parameters that the method takes
18 * and the value that it returns:
19 *
20 * MethodDescriptor:
21 * ( ParameterDescriptor* ) ReturnDescriptor
22 *
23 * A parameter descriptor represents a parameter passed to a method:
24 *
25 * ParameterDescriptor:
26 * FieldType
27 *
28 * A return descriptor represents the type of the value returned from a method.
29 * It is a series of characters generated by the grammar:
30 *
31 * ReturnDescriptor:
32 * FieldType
33 * V
34 *
35 * The character V indicates that the method returns no value
36 * (its return type is void).
37 *</code>
38 *
39 *<code>
40 * A field descriptor represents the type of a class, instance, or local
41 * variable. It is a series of characters generated by the grammar:
42 *
43 * FieldDescriptor:
44 * FieldType
45 *
46 * ComponentType:
47 * FieldType
48 *
49 * FieldType:
50 * BaseType
51 * ObjectType
52 * ArrayType
53 *
54 * BaseType:
55 * B
56 * C
57 * D
58 * F
59 * I
60 * J
61 * S
62 * Z
63 *
64 * ObjectType:
65 * L <classname> ;
66 *
67 * ArrayType:
68 * [ ComponentType
69 *
70 * The characters of BaseType, the L and ; of ObjectType, and the [ of
71 * ArrayType are all ASCII characters. The <classname> represents a fully
72 * qualified class or interface name. For historical reasons it is encoded in
73 * internal form (4.2). The interpretation of the field types is as shown
74 * in Table 4.2.
75 *
76 * BaseType Character Type Interpretation
77 * ----------------------------------------------
78 * B byte signed byte
79 * C char Unicode character
80 * D double double-precision floating-point value
81 * F float single-precision floating-point value
82 * I int integer
83 * J long long integer
84 * L<classname>; reference an instance of class <classname>
85 * S short signed short
86 * Z boolean true or false
87 * [ reference one array dimension
88 *
89 *
90 *
91 * @author <a href="mailto:mpollack@speakeasy.org">Mark Pollack</a>
92 */
93
94 public class DescriptorUtil {
95
96 private static Map _paramTypeMap = new HashMap();
97 private static Map _returnTypeMap = new HashMap();
98
99 static {
100 _paramTypeMap.put("byte", "B");
101 _paramTypeMap.put("char", "C");
102 _paramTypeMap.put("double", "D");
103 _paramTypeMap.put("float", "F");
104 _paramTypeMap.put("int", "I");
105 _paramTypeMap.put("long", "J");
106 //todo: make generic...look for 'dots' of package. that algorithm
107 //doesn't handle packageless (default package) classes though..
108 // _paramTypeMap.put("object reference","L<classname>")
109 _paramTypeMap.put("java.lang.Object", "Ljava/lang/Object;");
110 _paramTypeMap.put("short", "S");
111 _paramTypeMap.put("boolean", "Z");
112 //todo
113 _paramTypeMap.put("array reference", "[");
114
115 _returnTypeMap.put("void", "V");
116
117 }
118
119 /***
120 * Converts from the Java/Javadoc method signature the JVM spec format.
121 *
122 * TODO This class is poorly implemented and the code base no
123 * longer depends on it. Think about removing it.
124 *
125 * @param javadocSig method signature as returned via Javadoc API.
126 * @param javadocReturnType return type as returned via Javadoc API.
127 * @return mtehod signature as defined in the JVM spec.
128 */
129 public static String convert(String javadocSig, String javadocReturnType) {
130 //remove the leading and trailing parens
131 String javadocSigTrim =
132 javadocSig.substring(1, javadocSig.length() - 1);
133 StringTokenizer st = new StringTokenizer(javadocSigTrim, ",");
134 StringBuffer jvmBuff = new StringBuffer("(");
135 while (st.hasMoreTokens()) {
136 //remove the leading space character.
137 String sigElement = st.nextToken().trim();
138 if (_paramTypeMap.containsKey(sigElement)) {
139 jvmBuff.append(_paramTypeMap.get(sigElement));
140 } else {
141 Log.log(
142 "could not find javadoc parameter signature element "
143 + sigElement
144 + " in conversion map",
145 Log.ERROR,
146 "DescriptorUtil");
147 }
148
149 }
150 jvmBuff.append(")");
151 if (_returnTypeMap.containsKey(javadocReturnType)) {
152 jvmBuff.append(_returnTypeMap.get(javadocReturnType));
153 } else {
154 Log.log(
155 "could not find javadoc return signature "
156 + javadocReturnType
157 + " in conversion map",
158 Log.ERROR,
159 "DescriptorUtil");
160 }
161 return jvmBuff.toString();
162 }
163
164 /***
165 * Convert a method signature as definedin the JVM spec to that used
166 * in the Javadoc API. The BCEL library gives method signatures in
167 * the JVM format.
168 *
169 * @param bcelSignature The JVM format of a method signature.
170 * @return a <code>String[]</code> containing the method parameter as
171 * elements of the array.
172 */
173 public static String[] convertToJavaFormat(String bcelSignature) {
174 int i = 0;
175 if (bcelSignature.charAt(i) != '(') {
176 Log.log(
177 "BCEL signature didn't start with (. Can't convert "
178 + bcelSignature
179 + "> to javadoc representation",
180 Log.ERROR,
181 "DescriptorUtil");
182 return null;
183 }
184
185 int j = 0;
186 StringBuffer stringbuffer = new StringBuffer();
187 for (i++; i < bcelSignature.length();) {
188 if (bcelSignature.charAt(i) == ')') {
189 i++;
190 break; //we are at the end of the signature.
191 }
192 if (i > 1) {
193 //put in spaces to later tokenize on.
194 stringbuffer.append(" ");
195 }
196 i = jvmFormatToJavaFormat(bcelSignature, i, stringbuffer);
197 //count number of elements parsed.
198 j++;
199 }
200
201 //convert to string array.
202 String convertedString = stringbuffer.toString();
203 String as[] = new String[j];
204
205 int k = 0;
206 StringTokenizer st = new StringTokenizer(convertedString);
207 while (st.hasMoreTokens()) {
208 as[k++] = st.nextToken();
209 }
210 return as;
211
212 }
213
214 /***
215 * The utility method that does the real work of parsing through
216 * the JVM formatted string and adding an converted method parameter
217 * description to the StringBuffer.
218 *
219 * @param s The JVM formatted string that is being parsed.
220 * @param i The offset into the string being parsed.
221 * @param stringbuffer The storage for building the converted method
222 * signature.
223 * @return new offset location for parsing.
224 */
225 private static int jvmFormatToJavaFormat(
226 String jvmFormat,
227 int i,
228 StringBuffer stringbuffer) {
229 String s1 = "";
230 //arrays.
231 for (; jvmFormat.charAt(i) == '['; i++) {
232 s1 = s1 + "[]";
233 }
234
235 startover : switch (jvmFormat.charAt(i)) {
236 case 66 : // 'B'
237 stringbuffer.append("byte");
238 break;
239
240 case 67 : // 'C'
241 stringbuffer.append("char");
242 break;
243
244 case 68 : // 'D'
245 stringbuffer.append("double");
246 break;
247
248 case 70 : // 'F'
249 stringbuffer.append("float");
250 break;
251
252 case 73 : // 'I'
253 stringbuffer.append("int");
254 break;
255
256 case 74 : // 'J'
257 stringbuffer.append("long");
258 break;
259
260 case 83 : // 'S'
261 stringbuffer.append("short");
262 break;
263
264 case 90 : // 'Z'
265 stringbuffer.append("boolean");
266 break;
267
268 case 86 : // 'V'
269 stringbuffer.append("void");
270 break;
271
272 case 76 : // 'L'
273 //special case for objects.
274 for (i++; i < jvmFormat.length(); i++) {
275 if (jvmFormat.charAt(i) == '/') {
276 //convert to period
277 stringbuffer.append('.');
278 } else {
279 if (jvmFormat.charAt(i) == ';') {
280 //we reached the end
281 break startover;
282 }
283 //copy contents.
284 stringbuffer.append(jvmFormat.charAt(i));
285 }
286 }
287 break;
288
289 default :
290 Log.log(
291 "Can't convert jvm fromat "
292 + jvmFormat
293 + " to javadoc representation",
294 Log.ERROR,
295 "DescriptorUtil");
296 return jvmFormat.length();
297 }
298 stringbuffer = stringbuffer.append(s1);
299 return ++i;
300 }
301
302 } // DescriptorUtil
This page was automatically generated by Maven