001: /*
002:
003: Derby - Class org.apache.derby.iapi.services.classfile.ClassHolder
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to you under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.iapi.services.classfile;
023:
024: import org.apache.derby.iapi.services.sanity.SanityManager;
025:
026: import java.io.InputStream;
027: import java.io.OutputStream;
028: import java.util.Enumeration;
029:
030: import java.io.IOException;
031: import java.util.Vector;
032:
033: import org.apache.derby.iapi.util.ByteArray;
034: import org.apache.derby.iapi.services.classfile.VMDescriptor;
035: import org.apache.derby.iapi.services.classfile.VMDescriptor;
036:
037: import java.util.Hashtable;
038: import java.util.Vector;
039: import java.util.Enumeration;
040:
041: /** Based upon "THE class FILE FORMAT" chapter of "The Java Virtual Machine Specification"
042: corresponding to version 1.0.2 of the Java Virtual Machine and 1.0.2 of the
043: Java Language Specification.
044:
045: ISBN 0-201-63452-X, September 1996.
046: */
047:
048: public class ClassHolder {
049:
050: /*
051: ** Constants.
052: */
053:
054: /*
055: ** Fields
056: */
057:
058: protected int access_flags;
059: protected int this _class;
060: protected int super _class;
061:
062: // protected InterfacesArray interfaces; // can be null
063: protected int[] interfaces; //can be null
064:
065: protected MemberTable field_info; // can be null
066: protected MemberTable method_info; // can be null
067: protected Attributes attribute_info; // can be null
068:
069: /*
070: ** Fields for Constant Pool Table
071: */
072: protected Hashtable cptHashTable;
073: protected Vector cptEntries;
074: private int cptEstimatedSize;
075:
076: /**
077: Used to search for index entries to avoid object allocation
078: in the case a referecne already exists.
079: */
080: private final CONSTANT_Index_info searchIndex = new CONSTANT_Index_info(
081: 0, 0, 0);
082:
083: /*
084: ** Constructors.
085: */
086:
087: protected ClassHolder(int estimatedConstantPoolCount) {
088: // Constant Pool Information
089: // 100 is the estimate of the number of entries that will be generated
090: cptEntries = new Vector(estimatedConstantPoolCount);
091: cptHashTable = new Hashtable(estimatedConstantPoolCount,
092: (float) 0.75);
093:
094: // reserve the 0'th constant pool entry
095: cptEntries.setSize(1);
096: }
097:
098: /**
099: This will not define a constructor -- it is up
100: to the caller to add at least one.
101: */
102:
103: public ClassHolder(String fullyQualifiedName,
104: String super ClassName, int modifiers) {
105:
106: this (100);
107:
108: access_flags = modifiers | /* Modifier.SUPER */0x0020;
109:
110: this _class = addClassReference(fullyQualifiedName);
111: super _class = addClassReference(super ClassName);
112: method_info = new MemberTable(0);
113: }
114:
115: private void put(ClassFormatOutput out) throws IOException {
116:
117: /* Write out the header */
118: out.putU4(VMDescriptor.JAVA_CLASS_FORMAT_MAGIC);
119: out.putU2(VMDescriptor.JAVA_CLASS_FORMAT_MINOR_VERSION);
120: out.putU2(VMDescriptor.JAVA_CLASS_FORMAT_MAJOR_VERSION);
121:
122: // special case checking that the number of constant
123: // pool entries does not exceed the limit of 65535
124: // (as it is stored as a U2).
125: // Special case to allow somewhat easier debugging
126: // of the resulting failure.
127: out.putU2("constant_pool", cptEntries.size());
128: cptPut(out);
129:
130: out.putU2(access_flags);
131: out.putU2(this _class);
132: out.putU2(super _class);
133:
134: if (interfaces != null) {
135: int ilen = interfaces.length;
136: out.putU2(ilen);
137: for (int i = 0; i < ilen; i++) {
138: out.putU2(interfaces[i]);
139: }
140: } else {
141: out.putU2(0);
142: }
143:
144: if (field_info != null) {
145: out.putU2(field_info.size());
146: field_info.put(out);
147: } else {
148: out.putU2(0);
149: }
150:
151: if (method_info != null) {
152: out.putU2(method_info.size());
153: method_info.put(out);
154: } else {
155: out.putU2(0);
156: }
157:
158: if (attribute_info != null) {
159: out.putU2(attribute_info.size());
160: attribute_info.put(out);
161: } else {
162: out.putU2(0);
163: }
164:
165: }
166:
167: /*
168: ** Public methods from ClassHolder.
169: */
170:
171: /**
172: * Convert the object representation of the class into
173: * its class file format.
174: * @exception IOException error writing the class
175: */
176: public ByteArray getFileFormat() throws IOException {
177:
178: int classFileSize = 4 + (10 * 2);
179: classFileSize += cptEstimatedSize;
180:
181: if (interfaces != null)
182: classFileSize += (interfaces.length * 2);
183:
184: if (field_info != null)
185: classFileSize += field_info.classFileSize();
186:
187: if (method_info != null)
188: classFileSize += method_info.classFileSize();
189:
190: if (attribute_info != null)
191: classFileSize += attribute_info.classFileSize();
192:
193: ClassFormatOutput cfo = new ClassFormatOutput(
194: classFileSize + 200);
195:
196: put(cfo);
197:
198: return new ByteArray(cfo.getData(), 0, cfo.size());
199:
200: }
201:
202: /*
203: ** Public methods from ClassMember
204: */
205:
206: /** @see ClassMember
207: */
208: public int getModifier() {
209: return access_flags;
210: }
211:
212: /** @see ClassMember
213: */
214: public String getName() {
215: return className(this _class).replace('/', '.');
216: }
217:
218: /*
219: ** Public methods from ClassHolder
220: */
221:
222: /** @see ClassHolder#addMember */
223: public ClassMember addMember(String simpleName, String descriptor,
224: int modifier) {
225: if (SanityManager.DEBUG) {
226: if (descriptor.startsWith("(")) {
227: if (method_info != null) {
228: if (method_info.find(simpleName, descriptor) != null) {
229: SanityManager
230: .THROWASSERT("Method already exists "
231: + simpleName + " " + descriptor);
232: }
233: }
234:
235: } else {
236: if (field_info != null) {
237: if (field_info.find(simpleName, descriptor) != null) {
238: SanityManager
239: .THROWASSERT("Field already exists "
240: + simpleName + " " + descriptor);
241: }
242: }
243: }
244: }
245:
246: CONSTANT_Utf8_info utf = addUtf8Entry(simpleName);
247:
248: int nameIndex = utf.getIndex();
249: int descriptorIndex = addUtf8Entry(descriptor).getIndex();
250:
251: ClassMember item = new ClassMember(this , modifier, nameIndex,
252: descriptorIndex);
253: MemberTable mt;
254: if (descriptor.startsWith("(")) {
255: mt = method_info;
256: if (mt == null)
257: mt = method_info = new MemberTable(0);
258:
259: } else {
260: mt = field_info;
261: if (mt == null)
262: mt = field_info = new MemberTable(0);
263: }
264:
265: mt.addEntry(item);
266: return item;
267: }
268:
269: /** @see ClassHolder#addFieldReference */
270: public int addFieldReference(String className, String simpleName,
271: String descriptor) {
272: return addReference(VMDescriptor.CONSTANT_Fieldref, className,
273: simpleName, descriptor);
274: }
275:
276: public int addFieldReference(ClassMember field) {
277: return addReference(VMDescriptor.CONSTANT_Fieldref,
278: (ClassMember) field);
279: }
280:
281: /** @see ClassHolder#addMethodReference */
282: public int addMethodReference(String className, String simpleName,
283: String descriptor, boolean isInterface) {
284:
285: int tag = isInterface ? VMDescriptor.CONSTANT_InterfaceMethodref
286: : VMDescriptor.CONSTANT_Methodref;
287:
288: return addReference(tag, className, simpleName, descriptor);
289: }
290:
291: private int addReference(int tag, String className,
292: String simpleName, String descriptor) {
293:
294: int classIndex = addClassReference(className);
295: int nameTypeIndex = addNameAndType(simpleName, descriptor);
296:
297: return addIndexReference(tag, classIndex, nameTypeIndex);
298: }
299:
300: private int addReference(int tag, ClassMember member) {
301:
302: int nameTypeIndex = addIndexReference(
303: VMDescriptor.CONSTANT_NameAndType, member.name_index,
304: member.descriptor_index);
305:
306: return addIndexReference(tag, this _class, nameTypeIndex);
307: }
308:
309: /** @see ClassHolder#addConstant */
310: public int addConstant(String value) {
311:
312: return addString(value);
313: }
314:
315: /** @see ClassHolder#addUtf8 */
316: public int addUtf8(String value) {
317:
318: return addUtf8Entry(value).getIndex();
319: }
320:
321: /** @see ClassHolder#addConstant */
322: public int addConstant(int value) {
323: return addDirectEntry(new CONSTANT_Integer_info(value));
324: }
325:
326: /** @see ClassHolder#addConstant */
327: public int addConstant(float value) {
328: return addDirectEntry(new CONSTANT_Float_info(value));
329: }
330:
331: /** @see ClassHolder#addConstant */
332: public int addConstant(long value) {
333: return addDirectEntry(new CONSTANT_Long_info(value));
334: }
335:
336: /** @see ClassHolder#addConstant */
337: public int addConstant(double value) {
338: return addDirectEntry(new CONSTANT_Double_info(value));
339: }
340:
341: /** @see ClassMember
342: */
343: public int getConstantPoolIndex() {
344: return this _class;
345: }
346:
347: public void addAttribute(String attributeName,
348: ClassFormatOutput info) {
349:
350: if (attribute_info == null)
351: attribute_info = new Attributes(1);
352:
353: CONSTANT_Utf8_info autf = addUtf8Entry(attributeName);
354:
355: int index = autf.getIndex();
356:
357: attribute_info.addEntry(new AttributeEntry(index, info));
358: }
359:
360: public String getSuperClassName() {
361: if (super _class == 0)
362: return null;
363: else
364: return className(super _class).replace('/', '.');
365: }
366:
367: /*
368: public ClassMember getMemberReference(String fullyQualifiedClassName, String simpleName, String descriptor) {
369:
370: int classIndex;
371:
372: if (fullyQualifiedClassName == null)
373: classIndex = this_class;
374: else
375: classIndex = constantPool.findClass(fullyQualifiedClassName);
376:
377: if (classIndex < 0)
378: return null;
379:
380: int nameAndTypeIndex = constantPool.findNameAndType(simpleName, descriptor);
381: if (nameAndTypeIndex < 0)
382: return null;
383:
384: return constantPool.findReference(classIndex, nameAndTypeIndex);
385: }
386: */
387: /*
388: ** Public methods from ClassRead
389: */
390:
391: /*
392: ** Implementation specific methods.
393: */
394:
395: /*
396: ** Methods related to Constant Pool Table
397: */
398: /**
399: Generic add entry to constant pool. Includes the logic
400: for an entry to occupy more than one slot (e.g. long).
401:
402: @return The number of slots occupied by the entry.
403: .
404: */
405: protected int addEntry(Object key, ConstantPoolEntry item) {
406:
407: item.setIndex(cptEntries.size());
408: if (key != null)
409: cptHashTable.put(key, item);
410: cptEntries.addElement(item);
411:
412: cptEstimatedSize += item.classFileSize();
413:
414: if (item.doubleSlot()) {
415: cptEntries.addElement(null);
416: return 2;
417: } else {
418: return 1;
419: }
420: }
421:
422: /**
423: Add an entry, but only if it doesn't exist.
424:
425: @return the constant pool index of the added
426: or existing item.
427: */
428: private int addDirectEntry(ConstantPoolEntry item) {
429: ConstantPoolEntry existingItem = findMatchingEntry(item);
430: if (existingItem != null) {
431: item = existingItem;
432: //foundCount++;
433: } else {
434: addEntry(item.getKey(), item);
435: }
436: return item.getIndex();
437: }
438:
439: /**
440: Add an index reference.
441: */
442: private int addIndexReference(int tag, int i1, int i2) {
443:
444: // search for the item using the pre-allocated object
445: searchIndex.set(tag, i1, i2);
446:
447: ConstantPoolEntry item = findMatchingEntry(searchIndex);
448:
449: if (item == null) {
450: item = new CONSTANT_Index_info(tag, i1, i2);
451: addEntry(item.getKey(), item);
452: }
453:
454: return item.getIndex();
455: }
456:
457: /**
458: Add a class entry to the pool.
459: */
460: public int addClassReference(String fullyQualifiedName) {
461: if (ClassHolder.isExternalClassName(fullyQualifiedName)) {
462: fullyQualifiedName = ClassHolder
463: .convertToInternalClassName(fullyQualifiedName);
464: // System.out.println("addClassReference " + fullyQualifiedName);
465: }
466:
467: int name_index = addUtf8Entry(fullyQualifiedName).getIndex();
468:
469: return addIndexReference(VMDescriptor.CONSTANT_Class,
470: name_index, 0);
471: }
472:
473: /**
474: Add a name and type entry
475: */
476: private int addNameAndType(String name, String descriptor) {
477: int nameIndex = addUtf8Entry(name).getIndex();
478:
479: int descriptorIndex = addUtf8Entry(descriptor).getIndex();
480:
481: return addIndexReference(VMDescriptor.CONSTANT_NameAndType,
482: nameIndex, descriptorIndex);
483: }
484:
485: /**
486: Add a UTF8 into the pool and return the index to it.
487: */
488: private CONSTANT_Utf8_info addUtf8Entry(String value) {
489:
490: CONSTANT_Utf8_info item = (CONSTANT_Utf8_info) findMatchingEntry(value);
491:
492: if (item == null) {
493:
494: item = new CONSTANT_Utf8_info(value);
495: addEntry(value, item);
496: }
497: return item;
498: }
499:
500: /**
501: Add an extra UTF8 into the pool
502: */
503: private CONSTANT_Utf8_info addExtraUtf8(String value) {
504:
505: CONSTANT_Utf8_info item = new CONSTANT_Utf8_info(value);
506: addEntry(null, item);
507:
508: return item;
509: }
510:
511: /**
512: Add a string entry
513: */
514: private int addString(String value) {
515: CONSTANT_Utf8_info sutf = addUtf8Entry(value);
516: int valueIndex = sutf.setAsString();
517: if (valueIndex == 0) {
518: // string is already being used as code
519: valueIndex = addExtraUtf8(value).getIndex();
520: sutf.setAlternative(valueIndex);
521: }
522:
523: return addIndexReference(VMDescriptor.CONSTANT_String,
524: valueIndex, 0);
525: }
526:
527: /**
528: Add a string entry
529: */
530: private int addCodeUtf8(String value) {
531: CONSTANT_Utf8_info sutf = addUtf8Entry(value);
532: int index = sutf.setAsCode();
533: if (index == 0) {
534: // code string is already being used as string
535: CONSTANT_Utf8_info eutf = addExtraUtf8(value);
536: eutf.setAsCode(); // ensure the replace will happen
537: index = eutf.getIndex();
538: sutf.setAlternative(index);
539: }
540:
541: return index;
542: }
543:
544: protected void cptPut(ClassFormatOutput out) throws IOException {
545:
546: for (Enumeration e = cptEntries.elements(); e.hasMoreElements();) {
547: ConstantPoolEntry item = (ConstantPoolEntry) e
548: .nextElement();
549: if (item == null) {
550: continue;
551: }
552:
553: item.put(out);
554: }
555: }
556:
557: /*
558: ** Methods to convert indexes to constant pool entries and vice-versa.
559: */
560:
561: public ConstantPoolEntry getEntry(int index) {
562: return (ConstantPoolEntry) cptEntries.elementAt(index);
563: }
564:
565: /**
566: Return the class name for an index to a CONSTANT_Class_info.
567: */
568:
569: protected String className(int classIndex) {
570: CONSTANT_Index_info ci = (CONSTANT_Index_info) getEntry(classIndex);
571:
572: return nameIndexToString(ci.getI1()).replace('/', '.');
573:
574: }
575:
576: /*
577: ** Methods to find specific types of constant pool entries.
578: In these methods we try to avoid using the ConstantPoolEntry.matchValue()
579: as that requires creating a new object for the search. The matchValue()
580: call is really intended for when objects are being added to the constant pool.
581: */
582:
583: /**
584: Return the index of a UTF entry or -1 if it doesn't exist.
585: */
586: int findUtf8(String value) {
587:
588: ConstantPoolEntry item = findMatchingEntry(value);
589: if (item == null)
590: return -1;
591:
592: return item.getIndex();
593: }
594:
595: /**
596: Find a class descriptor (section 4.4.1) and return its
597: index, returns -1 if not found.
598: */
599: public int findClass(String fullyQualifiedName) {
600: String internalName = ClassHolder
601: .convertToInternalClassName(fullyQualifiedName);
602: int utf_index = findUtf8(internalName);
603: if (utf_index < 0)
604: return -1;
605:
606: return findIndexIndex(VMDescriptor.CONSTANT_Class, utf_index, 0);
607: }
608:
609: /**
610: Find a name and type descriptor (section 4.4.6) and
611: return it's index.
612: <p>
613: returns -1 if not found.
614: */
615: public int findNameAndType(String name, String descriptor) {
616:
617: int name_index = findUtf8(name);
618: if (name_index < 0)
619: return -1;
620: int descriptor_index = findUtf8(descriptor);
621: if (descriptor_index < 0)
622: return -1;
623:
624: return findIndexIndex(VMDescriptor.CONSTANT_NameAndType,
625: name_index, descriptor_index);
626: }
627:
628: /*
629: public ClassMember findReference(int classIndex, int nameAndTypeIndex) {
630:
631: CONSTANT_Index_info item = findIndexEntry(VMDescriptor.CONSTANT_Methodref,
632: classIndex, nameAndTypeIndex);
633:
634: if (item == null) {
635:
636: item = findIndexEntry(VMDescriptor.CONSTANT_InterfaceMethodref,
637: classIndex, nameAndTypeIndex);
638:
639: if (item == null) {
640: item = findIndexEntry(VMDescriptor.CONSTANT_Fieldref,
641: classIndex, nameAndTypeIndex);
642:
643: if (item == null)
644: return null;
645:
646: }
647: }
648:
649: return new ReferenceMember(this, item);
650: }
651: */
652: protected CONSTANT_Index_info findIndexEntry(int tag, int i1, int i2) {
653: // search for the item using the pre-allocated object
654: searchIndex.set(tag, i1, i2);
655:
656: return (CONSTANT_Index_info) findMatchingEntry(searchIndex);
657: }
658:
659: protected int findIndexIndex(int tag, int i1, int i2) {
660: CONSTANT_Index_info item = findIndexEntry(tag, i1, i2);
661: if (item == null)
662: return -1;
663:
664: return item.getIndex();
665: }
666:
667: protected ConstantPoolEntry findMatchingEntry(Object key) {
668: return (ConstantPoolEntry) cptHashTable.get(key);
669: }
670:
671: /** get a string (UTF) given a name_index into the constant pool
672: */
673: String nameIndexToString(int index) {
674:
675: return getEntry(index).toString();
676: }
677:
678: /** get the class name of a Class given the index of its CONSTANT_Class_info
679: entry in the Constant Pool.
680: */
681:
682: protected String getClassName(int index) {
683:
684: if (index == 0)
685: return ""; // must be the super class of java.lang.Object, ie. nothing.
686:
687: return nameIndexToString(getEntry(index).getI1());
688: }
689:
690: /*
691: * Determine whether the class descriptor string is
692: * in external format or not. Assumes that to be in external
693: * format means it must have a '.' or end in an ']'.
694: *
695: * @param className the name of the class to check
696: *
697: * @return true/false
698: */
699: public static boolean isExternalClassName(String className) {
700: int len;
701: if (className.indexOf('.') != -1) {
702: return true;
703: } else if ((len = className.length()) == 0) {
704: return false;
705: }
706: return (className.charAt(len - 1) == ']');
707: }
708:
709: /*
710: * Convert a class name to the internal VM class name format.
711: See sections 4.3.2, 4.4.1 of the vm spec.
712: * The normal leading 'L' and trailing ';' are left
713: * off of objects. This is intended primarily for
714: * the class manager.
715: * <p>
716: * An example of a conversion would be java.lang.Double[]
717: * to "[Ljava/lang/Double;".
718: <BR>
719: java.lang.Double would be converted to "java/lang/Double"
720:
721: <BR>
722: Note that for array types the result of convertToInternalClassName()
723: and convertToInternalDescriptor() are identical.
724:
725: *
726: * @param the external name (cannot be null)
727: *
728: * @return the internal string
729: */
730: public static String convertToInternalClassName(String externalName) {
731: return convertToInternal(externalName, false);
732: }
733:
734: /*
735: * Convert a class name to internal JVM descriptor format.
736: See sections 4.3.2 of the vm spec.
737: * <p>
738: * An example of a conversion would be "java.lang.Double[]"
739: * to "[Ljava/lang/Double;".
740: *
741: <BR>
742: java.lang.Double would be converted to "Ljava/lang/Double;"
743:
744: <BR>
745: Note that for array types the result of convertToInternalClassName()
746: and convertToInternalDescriptor() are identical.
747:
748: * @param the external name (cannot be null)
749: *
750: * @return the internal string
751: */
752: public static String convertToInternalDescriptor(String externalName) {
753: return convertToInternal(externalName, true);
754: }
755:
756: /*
757: ** Workhorse method. Convert to internal format.
758:
759: @param descriptor True if converting to descriptor format, false if
760: converting to class name format.
761: **
762: ** Lifted from BCClass.java.
763: **
764: ** Returns the result string.
765: */
766: private static String convertToInternal(String externalName,
767: boolean descriptor) {
768: if (SanityManager.DEBUG) {
769: SanityManager.ASSERT(externalName != null,
770: "unexpected null");
771: }
772:
773: int len = externalName.length();
774:
775: String internalName;
776: String retVal = null;
777: int origLen = len;
778: int arity = 0;
779:
780: // first walk through all array-ness
781: if (externalName.charAt(len - 1) == ']') {
782: while (len > 0 && externalName.charAt(len - 1) == ']'
783: && externalName.charAt(len - 2) == '[') {
784: len -= 2;
785: arity++;
786: }
787: }
788: if (SanityManager.DEBUG) {
789: SanityManager.ASSERT(len > 0);
790: }
791:
792: internalName = (origLen == len) ? externalName : externalName
793: .substring(0, len);
794:
795: // then check for primitive types ...
796: // in length by expected frequency order
797:
798: switch (len) {
799: case 7:
800: if ("boolean".equals(internalName)) {
801: retVal = makeDesc(VMDescriptor.C_BOOLEAN, arity);
802: }
803: break;
804: case 4:
805: if ("void".equals(internalName)) {
806: retVal = makeDesc(VMDescriptor.C_VOID, arity);
807: } else if ("long".equals(internalName)) {
808: retVal = makeDesc(VMDescriptor.C_LONG, arity);
809: } else if ("byte".equals(internalName)) {
810: retVal = makeDesc(VMDescriptor.C_BYTE, arity);
811: } else if ("char".equals(internalName)) {
812: retVal = makeDesc(VMDescriptor.C_CHAR, arity);
813: }
814: break;
815: case 3:
816: if ("int".equals(internalName)) {
817: retVal = makeDesc(VMDescriptor.C_INT, arity);
818: }
819: break;
820: case 6:
821: if ("double".equals(internalName)) {
822: retVal = makeDesc(VMDescriptor.C_DOUBLE, arity);
823: }
824: break;
825: case 5:
826: if ("short".equals(internalName)) {
827: retVal = makeDesc(VMDescriptor.C_SHORT, arity);
828: } else if ("float".equals(internalName)) {
829: retVal = makeDesc(VMDescriptor.C_FLOAT, arity);
830: }
831: break;
832: }
833:
834: // then it must be a Java class
835: if (retVal == null)
836: retVal = makeDesc(internalName, arity, descriptor);
837:
838: return retVal;
839: }
840:
841: /**
842: A helper to build a type description based on a built-in type
843: and an array arity.
844: */
845: static private String makeDesc(char builtin, int arity) {
846: if (arity == 0)
847: switch (builtin) {
848: case VMDescriptor.C_BYTE:
849: return VMDescriptor.BYTE;
850: case VMDescriptor.C_CHAR:
851: return VMDescriptor.CHAR;
852: case VMDescriptor.C_DOUBLE:
853: return VMDescriptor.DOUBLE;
854: case VMDescriptor.C_FLOAT:
855: return VMDescriptor.FLOAT;
856: case VMDescriptor.C_INT:
857: return VMDescriptor.INT;
858: case VMDescriptor.C_LONG:
859: return VMDescriptor.LONG;
860: case VMDescriptor.C_SHORT:
861: return VMDescriptor.SHORT;
862: case VMDescriptor.C_BOOLEAN:
863: return VMDescriptor.BOOLEAN;
864: case VMDescriptor.C_VOID:
865: return VMDescriptor.VOID;
866: default:
867: if (SanityManager.DEBUG)
868: SanityManager.THROWASSERT("No type match");
869: return null;
870: }
871: else {
872: StringBuffer desc = new StringBuffer(arity + 3);
873:
874: for (int i = 0; i < arity; i++)
875: desc.append(VMDescriptor.C_ARRAY);
876:
877: desc.append(ClassHolder.makeDesc(builtin, 0));
878:
879: return desc.toString();
880: }
881: }
882:
883: /**
884: A helper to build a type description based on a Java class
885: and an array arity.
886:
887: If descriptor is true create a descriptor according to
888: section 4.3.2 of the vm spec. If false create a class name
889: according to sections 4.3.2 and 4.4.1 of the vm spec.
890:
891: */
892: static private String makeDesc(String className, int arity,
893: boolean descriptor) {
894:
895: if (!descriptor && (arity == 0)) {
896: return className.replace('.', '/');
897: }
898:
899: StringBuffer desc = new StringBuffer(arity + 2
900: + className.length());
901:
902: for (int i = 0; i < arity; i++)
903: desc.append(VMDescriptor.C_ARRAY);
904:
905: desc.append(VMDescriptor.C_CLASS);
906:
907: desc.append(className.replace('.', '/'));
908:
909: desc.append(VMDescriptor.C_ENDCLASS);
910:
911: return desc.toString();
912: }
913:
914: }
|