KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > jdo > api > persistence > enhancer > classfile > Descriptor


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23
24
25 package com.sun.jdo.api.persistence.enhancer.classfile;
26
27 import java.util.Stack JavaDoc;
28 import java.util.Map JavaDoc;
29
30 //@olsen: subst: Hashtable -> Map, HashMap
31

32
33 /**
34  * A collection of static methods which manipulate type descriptors
35  */

36
37 public class Descriptor implements VMConstants {
38   /**
39    * Return the number of words of arguments to the method
40    * based on the method signature
41    */

42   public static int countMethodArgWords(String JavaDoc sig) {
43     if (sig.charAt(0) != '(')
44         throw new InsnError ("not a method signature");//NOI18N
45
int count = 0;
46     for (int idx = 1; sig.charAt(idx) != ')'; idx++) {
47       switch (sig.charAt(idx)) {
48       case 'B': /* byte */
49       case 'C': /* char */
50       case 'S': /* short */
51       case 'I': /* int */
52       case 'F': /* float */
53       case 'Z': /* boolean */
54     count++;
55     break;
56       case 'J': /* long */
57       case 'D': /* double */
58     count += 2;
59     break;
60       case 'L':
61     count++;
62     idx = sig.indexOf(';', idx);
63     break;
64       case '[':
65     count++;
66     while (sig.charAt(idx) == '[' || sig.charAt(idx) == ']')
67       idx++;
68     if (sig.charAt(idx) == 'L')
69       idx = sig.indexOf(';', idx);
70     /* else, let idx++ at loop iteration skip primitive descriptor */
71     break;
72       default:
73           throw new InsnError("missing case");//NOI18N
74
}
75     }
76     return count;
77   }
78
79   /**
80    * Return the number of words of return value for the method
81    * based on the method signature
82    */

83   public static int countMethodReturnWords(String JavaDoc sig) {
84     int idx = sig.lastIndexOf(')') + 1;
85     if (idx == 0)
86         throw new InsnError ("not a method signature");//NOI18N
87
switch (sig.charAt(idx)) {
88     case 'J': /* long */
89     case 'D': /* double */
90       return 2;
91     case 'B': /* byte */
92     case 'C': /* char */
93     case 'S': /* short */
94     case 'I': /* int */
95     case 'F': /* float */
96     case 'Z': /* boolean */
97     case 'L': /* object */
98     case '[': /* array */
99       return 1;
100     case 'V': /* void */
101       return 0;
102     default:
103         throw new InsnError("missing case");//NOI18N
104
}
105   }
106
107   /**
108    * Return the stack descriptor for the result of a method
109    * invocation. Void return values yield "V".
110    */

111   public static String JavaDoc extractResultSig(String JavaDoc methodSig) {
112     return methodSig.substring(methodSig.indexOf(')')+1);
113   }
114
115   /**
116    * Return the stack descriptor for the arguments to a method
117    * invocation (not including any "this" argument)
118    */

119   public static String JavaDoc extractArgSig(String JavaDoc methodSig) {
120     return methodSig.substring(1, methodSig.indexOf(')'));
121   }
122
123   /**
124    * Return the reversed stack descriptor for the arguments to a method
125    * invocation (not including any "this" argument). The top of stack
126    * element will be first.
127    */

128   public static String JavaDoc extractReversedArgSig(String JavaDoc methodSig) {
129     StringBuffer JavaDoc buf = new StringBuffer JavaDoc();;
130     reverseArgSig(buf, methodSig, 1);
131     return buf.toString();
132   }
133
134   /**
135    * Given a StringBuffer, a method descriptor, and a index to the
136    * start of an argument descriptor, append the arguments to the
137    * string buffer in reverse order.
138    */

139   private static void reverseArgSig(StringBuffer JavaDoc buf, String JavaDoc methodSig,
140                     int idx) {
141     char c = methodSig.charAt(idx);
142     if (c == ')')
143       return;
144     int startIdx = idx;
145
146     switch(c) {
147     case 'B':
148     case 'C':
149     case 'S':
150     case 'I':
151     case 'F':
152     case 'J':
153     case 'D':
154     case 'Z':
155       idx = idx+1;
156       break;
157     case '[':
158       while (methodSig.charAt(idx) == '[' || methodSig.charAt(idx) == ']')
159     idx++;
160       if (methodSig.charAt(idx) != 'L') {
161     idx++;
162     break;
163       }
164       /* fall through */
165     case 'L':
166       idx = methodSig.indexOf(';', idx) + 1;
167       break;
168     default:
169         throw new InsnError("bad signature char");//NOI18N
170
}
171
172     reverseArgSig(buf, methodSig, idx);
173     while (startIdx < idx)
174       buf.append(methodSig.charAt(startIdx++));
175   }
176
177   /**
178    * Return the number of words of a field based on its signature.
179    */

180   //@olsen: added method
181
public static int countFieldWords(String JavaDoc sig) {
182     if (sig == null || sig.length() < 1)
183         throw new InsnError ("not a field signature");//NOI18N
184
switch (sig.charAt(0)) {
185     case 'J': /* long */
186     case 'D': /* double */
187       return 2;
188     case 'B': /* byte */
189     case 'C': /* char */
190     case 'S': /* short */
191     case 'I': /* int */
192     case 'F': /* float */
193     case 'Z': /* boolean */
194     case 'L': /* object */
195     case '[': /* array */
196       return 1;
197     default:
198         throw new InsnError("missing case");//NOI18N
199
}
200   }
201
202   /**
203    * Return the element type for the first char in the type descriptor string.
204    */

205   //@olsen: added method
206
public static int elementType(String JavaDoc sig) {
207     if (sig == null || sig.length() < 1)
208         throw new InsnError ("not a value signature");//NOI18N
209
switch(sig.charAt(0)) {
210       case 'B':
211         return T_BOOLEAN;
212       case 'C':
213     return T_CHAR;
214       case 'Z':
215     return T_BYTE;
216       case 'S':
217     return T_SHORT;
218       case 'I':
219     return T_INT;
220       case 'J':
221     return T_LONG;
222       case 'F':
223     return T_FLOAT;
224       case 'D':
225     return T_DOUBLE;
226       case '[':
227     return TC_OBJECT;
228       case 'L':
229     return TC_OBJECT;
230       default:
231           throw new InsnError("bad signature char");//NOI18N
232
}
233   }
234
235   /**
236    * Return the element type descriptor char for the element type.
237    * The element type must be one of the T_ or TC_OBJECT.
238    */

239   public static String JavaDoc elementSig(int valueType) {
240     switch(valueType) {
241     case T_BYTE:
242         return "B";//NOI18N
243
case T_CHAR:
244         return "C";//NOI18N
245
case T_BOOLEAN:
246         return "Z";//NOI18N
247
case T_SHORT:
248         return "S";//NOI18N
249
case T_INT:
250         return "I";//NOI18N
251
case T_LONG:
252         return "J";//NOI18N
253
case T_FLOAT:
254         return "F";//NOI18N
255
case T_DOUBLE:
256         return "D";//NOI18N
257
case TC_OBJECT:
258         return "Ljava/lang/Object;";//NOI18N
259
default:
260         throw new InsnError("bad element type");//NOI18N
261
}
262   }
263
264   /**
265    * Return the number of stack words required for a value of the specified
266    * type on the operand stack.
267    */

268   public static int elementSize(int elementType) {
269     switch(elementType) {
270     case T_LONG:
271     case T_DOUBLE:
272     case T_TWOWORD:
273       return 2;
274     default:
275       return 1;
276     }
277   }
278
279   /**
280    * stackSig is a signature for a list of types on the JVM stack with the
281    * last type in the signature intended to be on the top of JVM stack.
282    * For each type in the signature, pushes an Integer objects identifying
283    * the types on top of the input Stack object.
284    */

285   public static void computeStackTypes(String JavaDoc stackSig, Stack JavaDoc stack) {
286     for (int idx = 0; idx < stackSig.length(); idx++) {
287       int tp = 0;
288       switch(stackSig.charAt(idx)) {
289       case 'B':
290       case 'C':
291       case 'Z':
292       case 'S':
293       case 'I':
294     tp = T_INT;
295     break;
296       case 'F':
297     tp = T_FLOAT;
298     break;
299       case 'J':
300     tp = T_LONG;
301     break;
302       case 'D':
303     tp = T_DOUBLE;
304     break;
305       case '?':
306     tp = T_UNKNOWN;
307     break;
308       case 'W':
309     tp = T_WORD;
310     break;
311       case 'X':
312     tp = T_TWOWORD;
313     break;
314       case 'A':
315     /* This isn't a real type, but any object refrence */
316     tp = TC_OBJECT;
317     break;
318       case '[':
319     tp = TC_OBJECT;
320     while (stackSig.charAt(idx) == '[' || stackSig.charAt(idx) == ']')
321       idx++;
322     if (stackSig.charAt(idx) != 'L')
323         break;
324     /* fall through */
325       case 'L':
326     tp = TC_OBJECT;
327     idx = stackSig.indexOf(';', idx);
328     break;
329       default:
330           throw new InsnError("bad signature char");//NOI18N
331
}
332       stack.push(new Integer JavaDoc(tp));
333     }
334   }
335
336   /**
337    * stackSig is a signature for the types on the stack with the last
338    * type in the signature on the top of stack. idx is the index of
339    * the start of a valid signature type element. Return the index of
340    * the next element (which may be past the end of the string).
341    */

342   public static int nextSigElement(String JavaDoc stackSig, int idx) {
343     switch(stackSig.charAt(idx)) {
344     case 'B':
345     case 'C':
346     case 'Z':
347     case 'S':
348     case 'I':
349     case 'F':
350     case 'J':
351     case 'D':
352       break;
353     case '[':
354       while (stackSig.charAt(idx) == '[' || stackSig.charAt(idx) == ']')
355     idx++;
356       if (stackSig.charAt(idx) != 'L')
357     break;
358       /* fall through */
359     case 'L':
360       idx = stackSig.indexOf(';', idx);
361       break;
362     default:
363         throw new InsnError("bad signature char");//NOI18N
364
}
365
366     idx++;
367     return idx;
368   }
369
370   /**
371    * classTranslations contains a set of mappings of class names.
372    * For any types within the input signature which appear as keys
373    * in the translation table, change the signature to replace the
374    * original type with the translation. Return a string containing
375    * the original signature with any translations applied.
376    */

377   public static String JavaDoc remapTypes(String JavaDoc sig, Map JavaDoc classTranslations) {
378     /* Defer allocation of the string buffer until it's needed */
379     StringBuffer JavaDoc buf = null;
380
381     for (int idx = 0; idx < sig.length(); idx++) {
382       char c;
383       switch(c = sig.charAt(idx)) {
384       case '[':
385     /* An array - skip through the [] pairs, copying to buf if not null */
386     while ((c = sig.charAt(idx)) == '[' || c == ']') {
387       idx++;
388       if (buf != null)
389         buf.append(c);
390     }
391
392     /* If the next char isnt 'L', the next char is a simple type and
393        will be handled by the default 1 char translation */

394     if (sig.charAt(idx) != 'L')
395       break;
396     /* fall through to type name translation */
397       case 'L':
398     /* This is a type name */
399     idx++;
400     int endIdx = sig.indexOf(';', idx);
401     String JavaDoc typeName = sig.substring(idx, endIdx);
402     String JavaDoc mapTo = (String JavaDoc) classTranslations.get(typeName);
403     if (mapTo != null) {
404       /* This type needs translation - allocate the string buffer
405          now if needed and copy in all up to this type name. */

406       if (buf == null) {
407         buf = new StringBuffer JavaDoc(sig.length() + 20);
408         buf.append(sig.substring(0,idx-1));
409       }
410       typeName = mapTo;
411     }
412
413     if (buf != null) {
414       buf.append('L');
415       buf.append(typeName);
416     }
417     idx = endIdx;
418     c = ';';
419     break;
420       }
421
422       if (buf != null)
423     buf.append(c);
424     }
425     return (buf == null) ? sig : (buf.toString());
426   }
427
428   /**
429    * classTranslations contains a set of mappings of class names.
430    * Translate the class name (which may be an array class) according
431    * to the entries in the translation table.
432    * Return either the original string if no translation applies or
433    * else the translated string.
434    */

435   public static String JavaDoc translateClass(
436     String JavaDoc cls, Map JavaDoc classTranslations) {
437     if (cls.charAt(0) == '[')
438       return remapTypes(cls, classTranslations);
439     else {
440       String JavaDoc mapTo = (String JavaDoc) classTranslations.get(cls);
441       if (mapTo != null)
442     return mapTo;
443       return cls;
444     }
445   }
446
447   /**
448    * Translates a VM type field signature into a user-format signature.
449    * Just a front for the two argument overload of this method.
450    */

451   public static String JavaDoc userFieldSig(String JavaDoc vmSig) {
452     return userFieldSig(vmSig, 0);
453   }
454
455   /**
456    * Translates a VM type field signature into a user-format signature.
457    */

458   public static String JavaDoc userFieldSig(String JavaDoc vmSig, int idx) {
459       String JavaDoc sigElement = "";//NOI18N
460
int arrayDims = 0;
461     boolean moreSig = true;
462     while (moreSig) {
463       moreSig = false;
464       char c = vmSig.charAt(idx);
465       switch (c) {
466       case 'B':
467           sigElement = "byte";//NOI18N
468
break;
469       case 'C':
470           sigElement = "char";//NOI18N
471
break;
472       case 'Z':
473           sigElement = "boolean";//NOI18N
474
break;
475       case 'S':
476           sigElement = "short";//NOI18N
477
break;
478       case 'I':
479           sigElement = "int";//NOI18N
480
break;
481       case 'F':
482           sigElement = "float";//NOI18N
483
break;
484       case 'J':
485           sigElement = "long";//NOI18N
486
break;
487       case 'D':
488           sigElement = "double";//NOI18N
489
break;
490       case 'V':
491     /* void isn't really valid as a field signature but this method
492        might be useful in implementing method signature conversion and
493        void is a valid return type. */

494           sigElement = "void";//NOI18N
495
break;
496       case '[':
497     idx++;
498     arrayDims++;
499     moreSig = true;
500     break;
501       case 'L':
502     int nextIdx = vmSig.indexOf(';', idx);
503     sigElement = vmSig.substring(idx+1,nextIdx).replace('/','.');
504     break;
505       default:
506           throw new InsnError("bad signature char");//NOI18N
507
}
508     }
509
510     /* If a non-array type, we already have the answer */
511     if (arrayDims == 0)
512       return sigElement;
513
514     /* array types need a little more work */
515     StringBuffer JavaDoc buf = new StringBuffer JavaDoc(sigElement.length() + 2 * arrayDims);
516     buf.append(sigElement);
517     while (arrayDims-- > 0)
518         buf.append("[]");//NOI18N
519

520     return buf.toString();
521   }
522
523   /**
524    * Produce a user consumable representation of a method argument list
525    * from the method signature. The return value is ignored.
526    */

527   public static String JavaDoc userMethodArgs(String JavaDoc methodSig) {
528     /* This better be a method signature */
529     if (methodSig.charAt(0) != '(')
530         throw new InsnError("Invalid method signature");//NOI18N
531

532     StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
533
534     buf.append('(');
535
536     int idx = 1;
537     boolean firstArg = true;
538     while (methodSig.charAt(idx) != ')') {
539       if (firstArg)
540     firstArg = false;
541       else
542           buf.append(", ");//NOI18N
543

544       buf.append(userFieldSig(methodSig, idx));
545       idx = nextSigElement(methodSig, idx);
546     }
547
548     buf.append(')');
549     return buf.toString();
550   }
551
552 }
553
Popular Tags