1 21 22 package org.apache.derby.iapi.services.classfile; 23 24 import org.apache.derby.iapi.services.sanity.SanityManager; 25 26 27 import java.io.InputStream ; 28 import java.io.OutputStream ; 29 import java.util.Enumeration ; 30 31 import java.io.IOException ; 32 import java.util.Vector ; 33 34 import org.apache.derby.iapi.util.ByteArray; 35 import org.apache.derby.iapi.services.classfile.VMDescriptor; 36 import org.apache.derby.iapi.services.classfile.VMDescriptor; 37 38 import java.util.Hashtable ; 39 import java.util.Vector ; 40 import java.util.Enumeration ; 41 42 43 49 50 public class ClassHolder { 51 52 53 56 57 60 61 protected int access_flags; 62 protected int this_class; 63 protected int super_class; 64 65 protected int[] interfaces; 68 protected MemberTable field_info; protected MemberTable method_info; protected Attributes attribute_info; 72 75 protected Hashtable cptHashTable; 76 protected Vector cptEntries; 77 private int cptEstimatedSize; 78 79 83 private final CONSTANT_Index_info searchIndex = new CONSTANT_Index_info(0, 0, 0); 84 85 88 89 protected ClassHolder(int estimatedConstantPoolCount) { 90 cptEntries = new Vector (estimatedConstantPoolCount); 93 cptHashTable = new Hashtable (estimatedConstantPoolCount, (float)0.75); 94 95 cptEntries.setSize(1); 97 } 98 99 100 104 105 public ClassHolder(String fullyQualifiedName, String superClassName, 106 int modifiers) { 107 108 this(100); 109 110 access_flags = modifiers | 0x0020; 111 112 this_class = addClassReference(fullyQualifiedName); 113 super_class = addClassReference(superClassName); 114 method_info = new MemberTable(0); 115 } 116 117 private void put(ClassFormatOutput out) throws IOException { 118 119 120 out.putU4(VMDescriptor.JAVA_CLASS_FORMAT_MAGIC); 121 out.putU2(VMDescriptor.JAVA_CLASS_FORMAT_MINOR_VERSION); 122 out.putU2(VMDescriptor.JAVA_CLASS_FORMAT_MAJOR_VERSION); 123 124 out.putU2("constant_pool", cptEntries.size()); 130 cptPut(out); 131 132 out.putU2(access_flags); 133 out.putU2(this_class); 134 out.putU2(super_class); 135 136 if (interfaces != null) { 137 int ilen = interfaces.length; 138 out.putU2(ilen); 139 for (int i = 0; i < ilen; i++) { 140 out.putU2(interfaces[i]); 141 } 142 } else { 143 out.putU2(0); 144 } 145 146 if (field_info != null) { 147 out.putU2(field_info.size()); 148 field_info.put(out); 149 } else { 150 out.putU2(0); 151 } 152 153 if (method_info != null) { 154 out.putU2(method_info.size()); 155 method_info.put(out); 156 } else { 157 out.putU2(0); 158 } 159 160 if (attribute_info != null) { 161 out.putU2(attribute_info.size()); 162 attribute_info.put(out); 163 } else { 164 out.putU2(0); 165 } 166 167 } 168 169 170 173 174 179 public ByteArray getFileFormat() throws IOException { 180 181 int classFileSize = 4 + (10 * 2); 182 classFileSize += cptEstimatedSize; 183 184 if (interfaces != null) 185 classFileSize += (interfaces.length * 2); 186 187 if (field_info != null) 188 classFileSize += field_info.classFileSize(); 189 190 if (method_info != null) 191 classFileSize += method_info.classFileSize(); 192 193 if (attribute_info != null) 194 classFileSize += attribute_info.classFileSize(); 195 196 197 ClassFormatOutput cfo = new ClassFormatOutput(classFileSize + 200); 198 199 put(cfo); 200 201 return new ByteArray(cfo.getData(), 0, cfo.size()); 202 203 } 204 205 208 209 211 public int getModifier() { return access_flags; } 212 213 215 public String getName() { 216 return className(this_class).replace('/', '.'); 217 } 218 221 222 223 public ClassMember addMember(String simpleName, String descriptor, int modifier) 224 { 225 if (SanityManager.DEBUG) 226 { 227 if (descriptor.startsWith("(")) { 228 if (method_info != null) { 229 if (method_info.find(simpleName, descriptor) != null) { 230 SanityManager.THROWASSERT("Method already exists " + simpleName + " " + descriptor); 231 } 232 } 233 234 } else { 235 if (field_info != null) { 236 if (field_info.find(simpleName, descriptor) != null) { 237 SanityManager.THROWASSERT("Field already exists " + simpleName + " " + descriptor); 238 } 239 } 240 } 241 } 242 243 CONSTANT_Utf8_info utf = addUtf8Entry(simpleName); 244 245 int nameIndex = utf.getIndex(); 246 int descriptorIndex = addUtf8Entry(descriptor).getIndex(); 247 248 ClassMember item = new ClassMember(this, modifier, nameIndex, descriptorIndex); 249 MemberTable mt; 250 if (descriptor.startsWith("(")) { 251 mt = method_info; 252 if (mt == null) 253 mt = method_info = new MemberTable(0); 254 255 } 256 else { 257 mt = field_info; 258 if (mt == null) 259 mt = field_info = new MemberTable(0); 260 } 261 262 mt.addEntry(item); 263 return item; 264 } 265 266 267 public int addFieldReference(String className, String simpleName, String descriptor) { 268 return addReference(VMDescriptor.CONSTANT_Fieldref, className, simpleName, descriptor); 269 } 270 271 public int addFieldReference(ClassMember field) { 272 return addReference(VMDescriptor.CONSTANT_Fieldref, (ClassMember) field); 273 } 274 275 276 public int addMethodReference(String className, String simpleName, String descriptor, boolean isInterface) { 277 278 int tag = isInterface ? VMDescriptor.CONSTANT_InterfaceMethodref : 279 VMDescriptor.CONSTANT_Methodref; 280 281 return addReference(tag, className, simpleName, descriptor); 282 } 283 284 private int addReference(int tag, String className, String simpleName, String descriptor) { 285 286 int classIndex = addClassReference(className); 287 int nameTypeIndex = addNameAndType(simpleName, descriptor); 288 289 return addIndexReference(tag, classIndex, nameTypeIndex); 290 } 291 292 private int addReference(int tag, ClassMember member) { 293 294 int nameTypeIndex = addIndexReference(VMDescriptor.CONSTANT_NameAndType, 295 member.name_index, member.descriptor_index); 296 297 return addIndexReference(tag, this_class, nameTypeIndex); 298 } 299 300 301 public int addConstant(String value) { 302 303 return addString(value); 304 } 305 306 307 public int addUtf8(String value) { 308 309 return addUtf8Entry(value).getIndex(); 310 } 311 312 313 314 public int addConstant(int value) { 315 return addDirectEntry(new CONSTANT_Integer_info(value)); 316 } 317 318 319 public int addConstant(float value) { 320 return addDirectEntry(new CONSTANT_Float_info(value)); 321 } 322 323 324 public int addConstant(long value) { 325 return addDirectEntry(new CONSTANT_Long_info(value)); 326 } 327 328 329 public int addConstant(double value) { 330 return addDirectEntry(new CONSTANT_Double_info(value)); 331 } 332 333 334 336 public int getConstantPoolIndex() { return this_class; } 337 338 public void addAttribute(String attributeName, ClassFormatOutput info) { 339 340 if (attribute_info == null) 341 attribute_info = new Attributes(1); 342 343 344 CONSTANT_Utf8_info autf = addUtf8Entry(attributeName); 345 346 int index = autf.getIndex(); 347 348 attribute_info.addEntry(new AttributeEntry(index, info)); 349 } 350 351 352 public String getSuperClassName() { 353 if (super_class == 0) 354 return null; 355 else 356 return className(super_class).replace('/', '.'); 357 } 358 359 360 380 383 384 385 386 389 390 393 400 protected int addEntry(Object key, ConstantPoolEntry item) { 401 402 item.setIndex(cptEntries.size()); 403 if (key != null) 404 cptHashTable.put(key, item); 405 cptEntries.addElement(item); 406 407 cptEstimatedSize += item.classFileSize(); 408 409 if (item.doubleSlot()) { 410 cptEntries.addElement(null); 411 return 2; 412 } else { 413 return 1; 414 } 415 } 416 417 423 private int addDirectEntry(ConstantPoolEntry item) { 424 ConstantPoolEntry existingItem = findMatchingEntry(item); 425 if (existingItem != null) { 426 item = existingItem; 427 } 429 else { 430 addEntry(item.getKey(), item); 431 } 432 return item.getIndex(); 433 } 434 435 438 private int addIndexReference(int tag, int i1, int i2) { 439 440 searchIndex.set(tag, i1, i2); 442 443 ConstantPoolEntry item = findMatchingEntry(searchIndex); 444 445 if (item == null) { 446 item = new CONSTANT_Index_info(tag, i1, i2); 447 addEntry(item.getKey(), item); 448 } 449 450 return item.getIndex(); 451 } 452 453 456 public int addClassReference(String fullyQualifiedName) { 457 if (ClassHolder.isExternalClassName(fullyQualifiedName)) { 458 fullyQualifiedName = ClassHolder.convertToInternalClassName(fullyQualifiedName); 459 } 461 462 int name_index = addUtf8Entry(fullyQualifiedName).getIndex(); 463 464 return addIndexReference(VMDescriptor.CONSTANT_Class, name_index, 0); 465 } 466 467 470 private int addNameAndType(String name, String descriptor) { 471 int nameIndex = addUtf8Entry(name).getIndex(); 472 473 int descriptorIndex = addUtf8Entry(descriptor).getIndex(); 474 475 return addIndexReference(VMDescriptor.CONSTANT_NameAndType, nameIndex, descriptorIndex); 476 } 477 478 481 private CONSTANT_Utf8_info addUtf8Entry(String value) { 482 483 CONSTANT_Utf8_info item = (CONSTANT_Utf8_info) findMatchingEntry(value); 484 485 if (item == null) { 486 487 item = new CONSTANT_Utf8_info(value); 488 addEntry(value, item); 489 } 490 return item; 491 } 492 495 private CONSTANT_Utf8_info addExtraUtf8(String value) { 496 497 CONSTANT_Utf8_info item = new CONSTANT_Utf8_info(value); 498 addEntry(null, item); 499 500 return item; 501 } 502 503 506 private int addString(String value) { 507 CONSTANT_Utf8_info sutf = addUtf8Entry(value); 508 int valueIndex = sutf.setAsString(); 509 if (valueIndex == 0) { 510 valueIndex = addExtraUtf8(value).getIndex(); 512 sutf.setAlternative(valueIndex); 513 } 514 515 return addIndexReference(VMDescriptor.CONSTANT_String, valueIndex, 0); 516 } 517 518 521 private int addCodeUtf8(String value) { 522 CONSTANT_Utf8_info sutf = addUtf8Entry(value); 523 int index = sutf.setAsCode(); 524 if (index == 0) { 525 CONSTANT_Utf8_info eutf = addExtraUtf8(value); 527 eutf.setAsCode(); index = eutf.getIndex(); 529 sutf.setAlternative(index); 530 } 531 532 return index; 533 } 534 protected void cptPut(ClassFormatOutput out) throws IOException { 535 536 for (Enumeration e = cptEntries.elements(); e.hasMoreElements(); ) { 537 ConstantPoolEntry item = (ConstantPoolEntry) e.nextElement(); 538 if (item == null) { 539 continue; 540 } 541 542 item.put(out); 543 } 544 } 545 546 549 550 public ConstantPoolEntry getEntry(int index) { 551 return (ConstantPoolEntry) cptEntries.elementAt(index); 552 } 553 554 557 558 protected String className(int classIndex) { 559 CONSTANT_Index_info ci = (CONSTANT_Index_info) getEntry(classIndex); 560 561 return nameIndexToString(ci.getI1()).replace('/', '.'); 562 563 } 564 565 571 572 575 int findUtf8(String value) { 576 577 ConstantPoolEntry item = findMatchingEntry(value); 578 if (item == null) 579 return -1; 580 581 return item.getIndex(); 582 } 583 584 588 public int findClass(String fullyQualifiedName) { 589 String internalName = ClassHolder.convertToInternalClassName(fullyQualifiedName); 590 int utf_index = findUtf8(internalName); 591 if (utf_index < 0) 592 return -1; 593 594 return findIndexIndex(VMDescriptor.CONSTANT_Class, 595 utf_index, 0); 596 } 597 598 599 605 public int findNameAndType(String name, String descriptor) { 606 607 int name_index = findUtf8(name); 608 if (name_index < 0) 609 return -1; 610 int descriptor_index = findUtf8(descriptor); 611 if (descriptor_index < 0) 612 return -1; 613 614 return findIndexIndex(VMDescriptor.CONSTANT_NameAndType, 615 name_index, descriptor_index); 616 } 617 641 protected CONSTANT_Index_info findIndexEntry(int tag, int i1, int i2) { 642 searchIndex.set(tag, i1, i2); 644 645 return (CONSTANT_Index_info) findMatchingEntry(searchIndex); 646 } 647 648 protected int findIndexIndex(int tag, int i1, int i2) { 649 CONSTANT_Index_info item = findIndexEntry(tag, i1, i2); 650 if (item == null) 651 return -1; 652 653 return item.getIndex(); 654 } 655 656 protected ConstantPoolEntry findMatchingEntry(Object key) { 657 return (ConstantPoolEntry) cptHashTable.get(key); 658 } 659 660 662 String nameIndexToString(int index) { 663 664 return getEntry(index).toString(); 665 } 666 667 670 671 protected String getClassName(int index) { 672 673 if (index == 0) 674 return ""; 676 return nameIndexToString(getEntry(index).getI1()); 677 } 678 679 688 public static boolean isExternalClassName(String className) 689 { 690 int len; 691 if (className.indexOf('.') != -1) 692 { 693 return true; 694 } 695 else if ((len = className.length()) == 0) 696 { 697 return false; 698 } 699 return (className.charAt(len - 1) == ']'); 700 } 701 702 723 public static String convertToInternalClassName(String externalName) 724 { 725 return convertToInternal(externalName, false); 726 } 727 728 746 public static String convertToInternalDescriptor(String externalName) 747 { 748 return convertToInternal(externalName, true); 749 } 750 751 761 private static String convertToInternal(String externalName, boolean descriptor) 762 { 763 if (SanityManager.DEBUG) 764 { 765 SanityManager.ASSERT(externalName != null, "unexpected null"); 766 } 767 768 int len = externalName.length(); 769 770 String internalName; 771 String retVal = null; 772 int origLen = len; 773 int arity = 0; 774 775 if (externalName.charAt(len-1) == ']') 777 { 778 while (len > 0 779 && externalName.charAt(len-1) == ']' 780 && externalName.charAt(len-2) == '[') 781 { 782 len -= 2; 783 arity++; 784 } 785 } 786 if (SanityManager.DEBUG) { 787 SanityManager.ASSERT(len > 0); 788 } 789 790 internalName = (origLen == len)? 791 externalName 792 : externalName.substring(0,len); 793 794 797 switch (len) { 798 case 7 : 799 if ("boolean".equals(internalName)) { 800 retVal = makeDesc(VMDescriptor.C_BOOLEAN, arity); 801 } 802 break; 803 case 4 : 804 if ("void".equals(internalName)) { 805 retVal = makeDesc(VMDescriptor.C_VOID, arity); 806 } 807 else if ("long".equals(internalName)) { 808 retVal = makeDesc(VMDescriptor.C_LONG, arity); 809 } 810 else if ("byte".equals(internalName)) { 811 retVal = makeDesc(VMDescriptor.C_BYTE, arity); 812 } 813 else if ("char".equals(internalName)) { 814 retVal = makeDesc(VMDescriptor.C_CHAR, arity); 815 } 816 break; 817 case 3 : 818 if ("int".equals(internalName)) { 819 retVal = makeDesc(VMDescriptor.C_INT, arity); 820 } 821 break; 822 case 6 : 823 if ("double".equals(internalName)) { 824 retVal = makeDesc(VMDescriptor.C_DOUBLE, arity); 825 } 826 break; 827 case 5 : 828 if ("short".equals(internalName)) { 829 retVal = makeDesc(VMDescriptor.C_SHORT, arity); 830 } 831 else if ("float".equals(internalName)) { 832 retVal = makeDesc(VMDescriptor.C_FLOAT, arity); 833 } 834 break; 835 } 836 837 if (retVal == null) 839 retVal = makeDesc(internalName, arity, descriptor); 840 841 return retVal; 842 } 843 844 848 static private String makeDesc (char builtin, int arity) { 849 if (arity == 0) 850 switch (builtin) { 851 case VMDescriptor.C_BYTE : return VMDescriptor.BYTE; 852 case VMDescriptor.C_CHAR : return VMDescriptor.CHAR; 853 case VMDescriptor.C_DOUBLE : return VMDescriptor.DOUBLE; 854 case VMDescriptor.C_FLOAT : return VMDescriptor.FLOAT; 855 case VMDescriptor.C_INT : return VMDescriptor.INT; 856 case VMDescriptor.C_LONG : return VMDescriptor.LONG; 857 case VMDescriptor.C_SHORT : return VMDescriptor.SHORT; 858 case VMDescriptor.C_BOOLEAN : return VMDescriptor.BOOLEAN; 859 case VMDescriptor.C_VOID : return VMDescriptor.VOID; 860 default: 861 if (SanityManager.DEBUG) 862 SanityManager.THROWASSERT("No type match"); 863 return null; 864 } 865 else { 866 StringBuffer desc = new StringBuffer (arity+3); 867 868 for (int i=0;i<arity;i++) 869 desc.append(VMDescriptor.C_ARRAY); 870 871 desc.append(ClassHolder.makeDesc(builtin, 0)); 872 873 return desc.toString(); 874 } 875 } 876 877 886 static private String makeDesc (String className, int arity, boolean descriptor) { 887 888 if (!descriptor && (arity == 0)) { 889 return className.replace('.','/'); 890 } 891 892 StringBuffer desc = new StringBuffer (arity+2+className.length()); 893 894 for (int i=0;i<arity;i++) 895 desc.append(VMDescriptor.C_ARRAY); 896 897 desc.append(VMDescriptor.C_CLASS); 898 899 desc.append(className.replace('.','/')); 900 901 desc.append(VMDescriptor.C_ENDCLASS); 902 903 return desc.toString(); 904 } 905 906 907 } 908 | Popular Tags |