1 19 package org.netbeans.mdr.util; 20 21 import java.io.ByteArrayOutputStream ; 22 import java.io.DataOutputStream ; 23 import java.io.IOException ; 24 import java.io.OutputStream ; 25 import java.lang.reflect.Method ; 26 import java.util.*; 27 28 32 public abstract class ImplGenerator { 33 34 35 public static final int JAVA_MAGIC = 0xcafebabe; 36 37 38 public static final int JAVA_DEFAULT_VERSION = 45; 39 public static final int JAVA_DEFAULT_MINOR_VERSION = 3; 40 41 42 public static final int CONSTANT_UTF8 = 1; 43 public static final int CONSTANT_INTEGER = 3; 44 public static final int CONSTANT_FLOAT = 4; 45 public static final int CONSTANT_LONG = 5; 46 public static final int CONSTANT_DOUBLE = 6; 47 public static final int CONSTANT_CLASS = 7; 48 public static final int CONSTANT_STRING = 8; 49 public static final int CONSTANT_FIELD = 9; 50 public static final int CONSTANT_METHOD = 10; 51 public static final int CONSTANT_INTERFACEMETHOD = 11; 52 public static final int CONSTANT_NAMEANDTYPE = 12; 53 54 55 public static final int ACC_PUBLIC = 0x00000001; 56 public static final int ACC_PRIVATE = 0x00000002; 57 public static final int ACC_PROTECTED = 0x00000004; 58 public static final int ACC_STATIC = 0x00000008; 59 public static final int ACC_FINAL = 0x00000010; 60 public static final int ACC_SUPER = 0x00000020; 61 62 63 int T_BYTE = 0x00000008; 64 65 66 public static final int opc_aconst_null = 1; 67 public static final int opc_iconst_0 = 3; 68 public static final int opc_lconst_0 = 9; 69 public static final int opc_fconst_0 = 11; 70 public static final int opc_dconst_0 = 14; 71 public static final int opc_bipush = 16; 72 public static final int opc_sipush = 17; 73 public static final int opc_ldc = 18; 74 public static final int opc_ldc_w = 19; 75 public static final int opc_iload = 21; 76 public static final int opc_lload = 22; 77 public static final int opc_fload = 23; 78 public static final int opc_dload = 24; 79 public static final int opc_aload = 25; 80 public static final int opc_iload_0 = 26; 81 public static final int opc_lload_0 = 30; 82 public static final int opc_fload_0 = 34; 83 public static final int opc_dload_0 = 38; 84 public static final int opc_aload_0 = 42; 85 public static final int opc_aaload = 50; 86 public static final int opc_istore = 54; 87 public static final int opc_lstore = 55; 88 public static final int opc_fstore = 56; 89 public static final int opc_dstore = 57; 90 public static final int opc_astore = 58; 91 public static final int opc_istore_0 = 59; 92 public static final int opc_lstore_0 = 63; 93 public static final int opc_fstore_0 = 67; 94 public static final int opc_dstore_0 = 71; 95 public static final int opc_astore_0 = 75; 96 public static final int opc_aastore = 83; 97 public static final int opc_bastore = 84; 98 public static final int opc_pop = 87; 99 public static final int opc_dup = 89; 100 public static final int opc_ifeq = 153; 101 public static final int opc_jsr = 168; 102 public static final int opc_ret = 169; 103 public static final int opc_ireturn = 172; 104 public static final int opc_lreturn = 173; 105 public static final int opc_freturn = 174; 106 public static final int opc_dreturn = 175; 107 public static final int opc_areturn = 176; 108 public static final int opc_return = 177; 109 public static final int opc_getstatic = 178; 110 public static final int opc_putstatic = 179; 111 public static final int opc_invokevirtual = 182; 112 public static final int opc_invokespecial = 183; 113 public static final int opc_invokestatic = 184; 114 public static final int opc_new = 187; 115 public static final int opc_newarray = 188; 116 public static final int opc_anewarray = 189; 117 public static final int opc_athrow = 191; 118 public static final int opc_checkcast = 192; 119 public static final int opc_wide = 196; 120 public static final int opc_ifnull = 198; 121 122 123 protected static final String FIELD_PREFIX = "field$"; 124 125 126 protected Class superclass; 127 128 129 protected String superclassName; 130 131 132 protected String className; 133 134 135 protected Class ifc; 136 137 138 protected ConstantPool cp = new ConstantPool(); 139 140 141 protected HashSet fields = new HashSet(); 142 143 144 protected List methods = new ArrayList(); 145 146 150 protected Map classMethods = new HashMap(11); 151 152 156 protected ImplGenerator(String className,Class ifc,Class handlerClass) { 157 this.className = className; 158 this.ifc = ifc; 159 this.superclass = handlerClass; 160 this.superclassName = dotToSlash(superclass.getName()); 161 } 162 163 167 final protected byte[] generateClassFile() { 168 171 176 { 178 Method [] methods = getMethodsToImplement(); 180 for (int i = 0; i < methods.length; i++) { 181 addClassMethod(methods[i], ifc); 183 } 185 } 186 187 try { 189 methods.add(generateConstructor()); 191 192 for (Iterator it = classMethods.values().iterator(); it.hasNext();) { 194 ClassMethod cm = (ClassMethod) it.next(); 195 196 methods.add(cm.generateMethod()); 198 } 199 200 methods.add(generateStaticInitializer()); 202 } catch (IOException e) { 203 throw new InternalError ("unexpected I/O Exception"); 204 } 205 206 cp.getClass(dotToSlash(className)); 208 cp.getClass(dotToSlash(superclass.getName())); 209 cp.getClass(dotToSlash(ifc.getName())); 210 cp.setReadOnly(); 211 212 ByteArrayOutputStream bout = new ByteArrayOutputStream (); 214 DataOutputStream dout = new DataOutputStream (bout); 215 216 try { 217 dout.writeInt(JAVA_MAGIC); 219 dout.writeShort(JAVA_DEFAULT_MINOR_VERSION); 221 dout.writeShort(JAVA_DEFAULT_VERSION); 223 224 cp.write(dout); 226 227 dout.writeShort(ACC_PUBLIC | ACC_FINAL | ACC_SUPER); 229 dout.writeShort(cp.getClass(dotToSlash(className))); 231 dout.writeShort(cp.getClass(dotToSlash(superclass.getName()))); 233 234 dout.writeShort(1); 236 dout.writeShort(cp.getClass(dotToSlash(ifc.getName()))); 238 239 dout.writeShort(fields.size()); 241 for (Iterator it = fields.iterator(); it.hasNext();) { 243 FieldInfo f = (FieldInfo) it.next(); 244 f.write(dout); 245 } 246 247 dout.writeShort(methods.size()); 249 for (Iterator it = methods.iterator(); it.hasNext();) { 251 MethodInfo m = (MethodInfo) it.next(); 252 m.write(dout); 253 } 254 255 dout.writeShort(0); 257 } catch (IOException e) { 258 throw new InternalError ("unexpected I/O Exception"); 259 } 260 261 return bout.toByteArray(); 262 } 263 264 267 protected void addClassMethod(Method m, Class fromClass) { 268 String name = m.getName(); 269 Class [] parameterTypes = m.getParameterTypes(); 270 String key = name + getParameterDescriptors(parameterTypes); 271 272 if (classMethods.get(key) == null) { 273 ClassMethod cm = getClassMethod(m, fromClass); 274 classMethods.put(key, cm); 275 } 276 } 277 278 protected abstract Method [] getMethodsToImplement(); 279 280 protected ClassMethod getClassMethod(Method m, Class fromClass) { 281 throw new InternalError ("Unrecognized method: " + m.getName() + " from class: " + fromClass.getName()); 283 } 284 285 290 final protected class FieldInfo { 291 public int accessFlags; 292 public String name; 293 public String descriptor; 294 295 public FieldInfo(String name, String descriptor, int accessFlags) { 296 this.name = name; 297 this.descriptor = descriptor; 298 this.accessFlags = accessFlags; 299 300 304 cp.getUtf8(name); 305 cp.getUtf8(descriptor); 306 } 307 308 final public void write(DataOutputStream out) throws IOException { 309 313 out.writeShort(accessFlags); 315 out.writeShort(cp.getUtf8(name)); 317 out.writeShort(cp.getUtf8(descriptor)); 319 out.writeShort(0); } 322 323 public boolean equals(Object o) { 324 if (o instanceof FieldInfo) { 325 return ((FieldInfo) o).name.equalsIgnoreCase(name); 326 } else { 327 return false; 328 } 329 } 330 331 public int hashCode() { 332 return name.toUpperCase(Locale.US).hashCode(); 333 } 334 } 335 336 341 final protected static class ExceptionTableEntry { 342 public short startPc; 343 public short endPc; 344 public short handlerPc; 345 public short catchType; 346 347 public ExceptionTableEntry(short startPc, short endPc, 348 short handlerPc, short catchType) 349 { 350 this.startPc = startPc; 351 this.endPc = endPc; 352 this.handlerPc = handlerPc; 353 this.catchType = catchType; 354 } 355 }; 356 357 362 final protected class MethodInfo { 363 public int accessFlags; 364 public String name; 365 public String descriptor; 366 public short maxStack; 367 public short maxLocals; 368 public ByteArrayOutputStream code = new ByteArrayOutputStream (); 369 public List exceptionTable = new ArrayList(); 370 public short[] declaredExceptions; 371 372 public MethodInfo(String name, String descriptor, int accessFlags) { 373 this.name = name; 374 this.descriptor = descriptor; 375 this.accessFlags = accessFlags; 376 377 381 cp.getUtf8(name); 382 cp.getUtf8(descriptor); 383 cp.getUtf8("Code"); 384 cp.getUtf8("Exceptions"); 385 } 386 387 public void write(DataOutputStream out) throws IOException { 388 392 out.writeShort(accessFlags); 394 out.writeShort(cp.getUtf8(name)); 396 out.writeShort(cp.getUtf8(descriptor)); 398 out.writeShort(2); 401 403 out.writeShort(cp.getUtf8("Code")); 405 out.writeInt(12 + code.size() + 8 * exceptionTable.size()); 407 out.writeShort(maxStack); 409 out.writeShort(maxLocals); 411 out.writeInt(code.size()); 413 code.writeTo(out); 415 out.writeShort(exceptionTable.size()); 417 for (Iterator iter = exceptionTable.iterator(); iter.hasNext();) { 418 ExceptionTableEntry e = (ExceptionTableEntry) iter.next(); 419 out.writeShort(e.startPc); 421 out.writeShort(e.endPc); 423 out.writeShort(e.handlerPc); 425 out.writeShort(e.catchType); 427 } 428 out.writeShort(0); 430 431 433 out.writeShort(cp.getUtf8("Exceptions")); 435 out.writeInt(2 + 2 * declaredExceptions.length); 437 out.writeShort(declaredExceptions.length); 439 for (int i = 0; i < declaredExceptions.length; i++) { 441 out.writeShort(declaredExceptions[i]); 442 } 443 } 444 445 } 446 447 452 protected class ClassMethod { 453 454 public String methodName; 455 public Class [] parameterTypes; 456 public Class returnType; 457 public Class [] exceptionTypes; 458 public Class fromClass; 459 public String methodFieldName; 460 public short delegateMethod; 461 private boolean hasField; 462 463 public ClassMethod(Method method, short delegate, String methodFieldName) 464 { 465 this.methodName = method.getName(); 466 this.parameterTypes = method.getParameterTypes(); 467 this.returnType = method.getReturnType(); 468 this.exceptionTypes = method.getExceptionTypes(); 469 this.fromClass = method.getDeclaringClass(); 470 if (methodFieldName == null) { 471 this.methodFieldName = null; 472 hasField = false; 473 } else { 474 this.methodFieldName = FIELD_PREFIX + methodFieldName; 475 hasField = fields.add(new FieldInfo(this.methodFieldName, "Ljava/lang/String;", ACC_PRIVATE | ACC_STATIC)); 477 } 478 delegateMethod = delegate; 479 } 480 481 485 public MethodInfo generateMethod() throws IOException { 486 String desc = getMethodDescriptor(parameterTypes, returnType); 487 MethodInfo minfo = new MethodInfo(methodName, desc, ACC_PUBLIC | ACC_FINAL); 488 int[] parameterSlot = new int[parameterTypes.length]; 489 int nextSlot = 1; 490 for (int i = 0; i < parameterSlot.length; i++) { 491 parameterSlot[i] = nextSlot; 492 nextSlot += getWordsPerType(parameterTypes[i]); 493 } 494 int localSlot0 = nextSlot; 495 496 DataOutputStream out = new DataOutputStream (minfo.code); 497 498 code_aload(0, out); 500 501 if (methodFieldName != null) { 502 out.writeByte(opc_dup); 504 out.writeByte(opc_getstatic); 505 out.writeShort(cp.getFieldRef(dotToSlash(className), methodFieldName, "Ljava/lang/String;")); 506 } 507 508 for (int i = 0; i < parameterTypes.length; i++) { 510 codeWrapArgument(parameterTypes[i], parameterSlot[i], out); 511 } 512 513 out.writeByte(opc_invokespecial); 515 out.writeShort(delegateMethod); 516 517 if (returnType == void.class) { 518 out.writeByte(opc_return); 520 } else { 521 codeUnwrapReturnValue(returnType, out); 522 } 523 524 minfo.maxStack = 10; 525 minfo.maxLocals = (short) (localSlot0 + 1); 526 minfo.declaredExceptions = new short[0]; 527 528 return minfo; 529 } 530 531 537 public void codeWrapArgument(Class type, int slot, DataOutputStream out) throws IOException { 538 if (type.isPrimitive()) { 539 if (type == boolean.class) { 540 code_iload(slot, out); 541 out.writeByte(opc_invokestatic); 542 out.writeShort(cp.getMethodRef("java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;")); 543 } else { 544 PrimitiveTypeInfo prim = PrimitiveTypeInfo.get(type); 545 546 out.writeByte(opc_new); 547 out.writeShort(cp.getClass(prim.wrapperClassName)); 548 549 out.writeByte(opc_dup); 550 551 if (type == int.class || type == byte.class || type == char.class || type == short.class) { 552 code_iload(slot, out); 553 } else if (type == long.class) { 554 code_lload(slot, out); 555 } else if (type == float.class) { 556 code_fload(slot, out); 557 } else if (type == double.class) { 558 code_dload(slot, out); 559 } else { 560 assertTrue(false); 561 } 562 563 out.writeByte(opc_invokespecial); 564 out.writeShort(cp.getMethodRef(prim.wrapperClassName, "<init>", prim.wrapperConstructorDesc)); 565 } 566 } else { 567 code_aload(slot, out); 568 } 569 } 570 571 576 public void codeUnwrapReturnValue(Class type, DataOutputStream out) throws IOException { 577 if (type.isPrimitive()) { 578 PrimitiveTypeInfo prim = PrimitiveTypeInfo.get(type); 579 580 out.writeByte(opc_dup); 581 out.writeByte(opc_ifnull); 582 out.writeShort(10); 583 584 out.writeByte(opc_checkcast); 585 out.writeShort(cp.getClass(prim.wrapperClassName)); 586 587 out.writeByte(opc_invokevirtual); 588 out.writeShort(cp.getMethodRef( 589 prim.wrapperClassName, 590 prim.unwrapMethodName, prim.unwrapMethodDesc)); 591 592 if (type == int.class || 593 type == boolean.class || 594 type == byte.class || 595 type == char.class || 596 type == short.class) 597 { 598 out.writeByte(opc_ireturn); 599 out.writeByte(opc_iconst_0); 600 out.writeByte(opc_ireturn); 601 } else if (type == long.class) { 602 out.writeByte(opc_lreturn); 603 out.writeByte(opc_lconst_0); 604 out.writeByte(opc_lreturn); 605 } else if (type == float.class) { 606 out.writeByte(opc_freturn); 607 out.writeByte(opc_fconst_0); 608 out.writeByte(opc_freturn); 609 } else if (type == double.class) { 610 out.writeByte(opc_dreturn); 611 out.writeByte(opc_dconst_0); 612 out.writeByte(opc_dreturn); 613 } else { 614 assertTrue(false); 615 } 616 617 } else { 618 619 out.writeByte(opc_checkcast); 620 out.writeShort(cp.getClass(dotToSlash(type.getName()))); 621 622 out.writeByte(opc_areturn); 623 } 624 } 625 626 public int getBytesForUnwrapReturn(Class type) { 627 if (type.isPrimitive()) { 628 return 13; 629 } else { 630 return 4; 631 } 632 } 633 634 639 public void codeFieldInitialization(DataOutputStream out) throws IOException { 640 if (hasField) { 641 out.writeByte(opc_new); out.writeShort(cp.getClass("java/lang/String")); out.writeByte(opc_dup); 645 byte[] bytes = strip(methodFieldName, FIELD_PREFIX).getBytes(); 647 648 code_ipush(bytes.length, out); out.writeByte(opc_newarray); out.writeByte(T_BYTE); 652 for (int i = 0; i < bytes.length; i++) { 654 out.writeByte(opc_dup); code_ipush(i, out); code_ipush(bytes[i], out); out.writeByte(opc_bastore); } 659 660 out.writeByte(opc_invokespecial); 664 out.writeShort(cp.getMethodRef("java/lang/String", "<init>", "([B)V")); 665 666 out.writeByte(opc_putstatic); 669 out.writeShort(cp.getFieldRef(dotToSlash(className), methodFieldName, "Ljava/lang/String;")); 670 } 671 } 672 } 673 674 677 protected abstract MethodInfo generateConstructor() throws IOException ; 678 679 682 protected MethodInfo generateStaticInitializer() throws IOException { 683 MethodInfo minfo = new MethodInfo( 684 "<clinit>", "()V", ACC_STATIC); 685 686 int localSlot0 = 1; 687 688 DataOutputStream out = new DataOutputStream (minfo.code); 689 690 for (Iterator it = classMethods.values().iterator(); it.hasNext();) { 691 ClassMethod cm = (ClassMethod) it.next(); 692 cm.codeFieldInitialization(out); 693 } 694 695 out.writeByte(opc_return); 696 697 minfo.maxStack = 10; 698 minfo.maxLocals = (short) (localSlot0 + 1); 699 minfo.declaredExceptions = new short[0]; 700 701 return minfo; 702 } 703 704 707 708 713 714 protected void code_iload(int lvar, DataOutputStream out) 715 throws IOException 716 { 717 codeLocalLoadStore(lvar, 718 opc_iload, opc_iload_0, out); 719 } 720 721 protected void code_lload(int lvar, DataOutputStream out) 722 throws IOException 723 { 724 codeLocalLoadStore(lvar, 725 opc_lload, opc_lload_0, out); 726 } 727 728 protected void code_fload(int lvar, DataOutputStream out) 729 throws IOException 730 { 731 codeLocalLoadStore(lvar, 732 opc_fload, opc_fload_0, out); 733 } 734 735 protected void code_dload(int lvar, DataOutputStream out) 736 throws IOException 737 { 738 codeLocalLoadStore(lvar, 739 opc_dload, opc_dload_0, out); 740 } 741 742 protected void code_aload(int lvar, DataOutputStream out) 743 throws IOException 744 { 745 codeLocalLoadStore(lvar, 746 opc_aload, opc_aload_0, out); 747 } 748 749 protected void code_istore(int lvar, DataOutputStream out) 750 throws IOException 751 { 752 codeLocalLoadStore(lvar, 753 opc_istore, opc_istore_0, out); 754 } 755 756 protected void code_lstore(int lvar, DataOutputStream out) 757 throws IOException 758 { 759 codeLocalLoadStore(lvar, 760 opc_lstore, opc_lstore_0, out); 761 } 762 763 protected void code_fstore(int lvar, DataOutputStream out) 764 throws IOException 765 { 766 codeLocalLoadStore(lvar, 767 opc_fstore, opc_fstore_0, out); 768 } 769 770 protected void code_dstore(int lvar, DataOutputStream out) 771 throws IOException 772 { 773 codeLocalLoadStore(lvar, 774 opc_dstore, opc_dstore_0, out); 775 } 776 777 protected void code_astore(int lvar, DataOutputStream out) 778 throws IOException 779 { 780 codeLocalLoadStore(lvar, 781 opc_astore, opc_astore_0, out); 782 } 783 784 793 protected void codeLocalLoadStore(int lvar, int opcode, int opcode_0, 794 DataOutputStream out) 795 throws IOException 796 { 797 assertTrue(lvar >= 0 && lvar <= 0xFFFF); 798 if (lvar <= 3) { 799 out.writeByte(opcode_0 + lvar); 800 } else if (lvar <= 0xFF) { 801 out.writeByte(opcode); 802 out.writeByte(lvar & 0xFF); 803 } else { 804 808 out.writeByte(opc_wide); 809 out.writeByte(opcode); 810 out.writeShort(lvar & 0xFFFF); 811 } 812 } 813 814 819 protected void code_ldc(int index, DataOutputStream out) 820 throws IOException 821 { 822 assertTrue(index >= 0 && index <= 0xFFFF); 823 if (index <= 0xFF) { 824 out.writeByte(opc_ldc); 825 out.writeByte(index & 0xFF); 826 } else { 827 out.writeByte(opc_ldc_w); 828 out.writeShort(index & 0xFFFF); 829 } 830 } 831 832 838 protected void code_ipush(int value, DataOutputStream out) 839 throws IOException 840 { 841 if (value >= -1 && value <= 5) { 842 out.writeByte(opc_iconst_0 + value); 843 } else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) { 844 out.writeByte(opc_bipush); 845 out.writeByte(value & 0xFF); 846 } else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) { 847 out.writeByte(opc_sipush); 848 out.writeShort(value & 0xFFFF); 849 } else { 850 assertTrue(false); 851 } 852 } 853 854 860 protected void codeClassForName(Class cl, DataOutputStream out) 861 throws IOException 862 { 863 code_ldc(cp.getString(cl.getName()), out); 864 865 out.writeByte(opc_invokestatic); 866 out.writeShort(cp.getMethodRef( 867 "java/lang/Class", 868 "forName", "(Ljava/lang/String;)Ljava/lang/Class;")); 869 } 870 873 874 876 protected static String strip( String methodName, String prefix ) { 877 return methodName.substring( prefix.length() ); 878 } 879 880 882 protected static String strip(String methodName, String prefix, String suffix) { 883 return methodName.substring(prefix.length(), methodName.length() - suffix.length()); 884 } 885 886 protected static String firstUpper(String text) { 887 try { 888 return text.substring(0, 1).toUpperCase(Locale.US) + text.substring(1); 889 } catch (IndexOutOfBoundsException e) { 890 return ""; 891 } 892 } 893 894 protected static String firstLower(String text) { 895 try { 896 return text.substring(0, 1).toLowerCase(Locale.US) + text.substring(1); 897 } catch (IndexOutOfBoundsException e) { 898 return ""; 899 } 900 } 901 902 905 protected static void assertTrue(boolean assertion) { 906 if (assertion != true) { 907 throw new InternalError ("assertion failure"); 908 } 909 } 910 911 918 protected static String dotToSlash(String name) { 919 return name.replace('.', '/'); 920 } 921 922 926 protected static String getMethodDescriptor(Class [] parameterTypes, 927 Class returnType) 928 { 929 return getParameterDescriptors(parameterTypes) + 930 ((returnType == void.class) ? "V" : getFieldType(returnType)); 931 } 932 933 940 protected static String getParameterDescriptors(Class [] parameterTypes) { 941 StringBuffer desc = new StringBuffer ("("); 942 for (int i = 0; i < parameterTypes.length; i++) { 943 desc.append(getFieldType(parameterTypes[i])); 944 } 945 desc.append(')'); 946 return desc.toString(); 947 } 948 949 954 protected static String getFieldType(Class type) { 955 if (type.isPrimitive()) { 956 return PrimitiveTypeInfo.get(type).baseTypeString; 957 } else if (type.isArray()) { 958 965 return type.getName().replace('.', '/'); 966 } else { 967 return "L" + dotToSlash(type.getName()) + ";"; 968 } 969 } 970 971 980 protected static int getWordsPerType(Class type) { 981 if (type == long.class || type == double.class) { 982 return 2; 983 } else { 984 return 1; 985 } 986 } 987 988 993 protected static class PrimitiveTypeInfo { 994 995 996 public String baseTypeString; 997 998 999 public String wrapperClassName; 1000 1001 1002 public String wrapperConstructorDesc; 1003 1004 1005 public String unwrapMethodName; 1006 1007 1008 public String unwrapMethodDesc; 1009 1010 private static Map table = new HashMap(11); 1011 static { 1012 table.put(int.class, new PrimitiveTypeInfo( 1013 "I", "java/lang/Integer", "(I)V", "intValue", "()I")); 1014 table.put(boolean.class, new PrimitiveTypeInfo( 1015 "Z", "java/lang/Boolean", "(Z)V", "booleanValue", "()Z")); 1016 table.put(byte.class, new PrimitiveTypeInfo( 1017 "B", "java/lang/Byte", "(B)V", "byteValue", "()B")); 1018 table.put(char.class, new PrimitiveTypeInfo( 1019 "C", "java/lang/Char", "(C)V", "charValue", "()C")); 1020 table.put(short.class, new PrimitiveTypeInfo( 1021 "S", "java/lang/Short", "(S)V", "shortValue", "()S")); 1022 table.put(long.class, new PrimitiveTypeInfo( 1023 "J", "java/lang/Long", "(J)V", "longValue", "()J")); 1024 table.put(float.class, new PrimitiveTypeInfo( 1025 "F", "java/lang/Float", "(F)V", "floatValue", "()F")); 1026 table.put(double.class, new PrimitiveTypeInfo( 1027 "D", "java/lang/Double", "(D)V", "doubleValue", "()D")); 1028 } 1029 1030 private PrimitiveTypeInfo(String baseTypeString, 1031 String wrapperClassName, 1032 String wrapperConstructorDesc, 1033 String unwrapMethodName, 1034 String unwrapMethodDesc) 1035 { 1036 this.baseTypeString = baseTypeString; 1037 this.wrapperClassName = wrapperClassName; 1038 this.wrapperConstructorDesc = wrapperConstructorDesc; 1039 this.unwrapMethodName = unwrapMethodName; 1040 this.unwrapMethodDesc = unwrapMethodDesc; 1041 } 1042 1043 public static PrimitiveTypeInfo get(Class cl) { 1044 return (PrimitiveTypeInfo) table.get(cl); 1045 } 1046 } 1047 1048 1049 1065 protected static class ConstantPool { 1066 1067 1074 private List pool = new ArrayList(32); 1075 1076 1082 private Map map = new HashMap(16); 1083 1084 1085 private boolean readOnly = false; 1086 1087 1090 public short getUtf8(String s) { 1091 if (s == null) { 1092 throw new NullPointerException (); 1093 } 1094 return getValue(s); 1095 } 1096 1097 1100 public short getInteger(int i) { 1101 return getValue(new Integer (i)); 1102 } 1103 1104 1107 public short getFloat(float f) { 1108 return getValue(new Float (f)); 1109 } 1110 1111 1114 public short getLong(long l) { 1115 return getValue(new Long (l)); 1116 } 1117 1118 1121 public short getDouble(double d) { 1122 return getValue(new Double (d)); 1123 } 1124 1125 1128 public short getClass(String name) { 1129 short utf8Index = getUtf8(name); 1130 return getIndirect(new IndirectEntry( 1131 CONSTANT_CLASS, utf8Index)); 1132 } 1133 1134 1137 public short getString(String s) { 1138 short utf8Index = getUtf8(s); 1139 return getIndirect(new IndirectEntry( 1140 CONSTANT_STRING, utf8Index)); 1141 } 1142 1143 1146 public short getFieldRef(String className, 1147 String name, String descriptor) 1148 { 1149 short classIndex = getClass(className); 1150 short nameAndTypeIndex = getNameAndType(name, descriptor); 1151 return getIndirect(new IndirectEntry( 1152 CONSTANT_FIELD, 1153 classIndex, nameAndTypeIndex)); 1154 } 1155 1156 1159 public short getMethodRef(String className, 1160 String name, String descriptor) 1161 { 1162 short classIndex = getClass(className); 1163 short nameAndTypeIndex = getNameAndType(name, descriptor); 1164 return getIndirect(new IndirectEntry( 1165 CONSTANT_METHOD, 1166 classIndex, nameAndTypeIndex)); 1167 } 1168 1169 1172 public short getInterfaceMethodRef(String className, String name, 1173 String descriptor) 1174 { 1175 short classIndex = getClass(className); 1176 short nameAndTypeIndex = getNameAndType(name, descriptor); 1177 return getIndirect(new IndirectEntry( 1178 CONSTANT_INTERFACEMETHOD, 1179 classIndex, nameAndTypeIndex)); 1180 } 1181 1182 1185 public short getNameAndType(String name, String descriptor) { 1186 short nameIndex = getUtf8(name); 1187 short descriptorIndex = getUtf8(descriptor); 1188 return getIndirect(new IndirectEntry( 1189 CONSTANT_NAMEANDTYPE, 1190 nameIndex, descriptorIndex)); 1191 } 1192 1193 1200 public void setReadOnly() { 1201 readOnly = true; 1202 } 1203 1204 1212 public void write(OutputStream out) throws IOException { 1213 DataOutputStream dataOut = new DataOutputStream (out); 1214 1215 dataOut.writeShort(pool.size() + 1); 1217 1218 for (Iterator iter = pool.iterator(); iter.hasNext();) { 1219 Entry e = (Entry) iter.next(); 1220 e.write(dataOut); 1221 } 1222 } 1223 1224 1227 private short addEntry(Entry entry) { 1228 pool.add(entry); 1229 return (short) pool.size(); 1230 } 1231 1232 1243 private short getValue(Object key) { 1244 Short index = (Short ) map.get(key); 1245 if (index != null) { 1246 return index.shortValue(); 1247 } else { 1248 if (readOnly) { 1249 throw new InternalError ( 1250 "late constant pool addition: " + key); 1251 } 1252 short i = addEntry(new ValueEntry(key)); 1253 map.put(key, new Short (i)); 1254 return i; 1255 } 1256 } 1257 1258 1262 private short getIndirect(IndirectEntry e) { 1263 Short index = (Short ) map.get(e); 1264 if (index != null) { 1265 return index.shortValue(); 1266 } else { 1267 if (readOnly) { 1268 throw new InternalError ("late constant pool addition"); 1269 } 1270 short i = addEntry(e); 1271 map.put(e, new Short (i)); 1272 return i; 1273 } 1274 } 1275 1276 1281 private static abstract class Entry { 1282 public abstract void write(DataOutputStream out) 1283 throws IOException ; 1284 } 1285 1286 1294 private static class ValueEntry extends Entry { 1295 private Object value; 1296 1297 public ValueEntry(Object value) { 1298 this.value = value; 1299 } 1300 1301 public void write(DataOutputStream out) throws IOException { 1302 if (value instanceof String ) { 1303 out.writeByte(CONSTANT_UTF8); 1304 out.writeUTF((String ) value); 1305 } else if (value instanceof Integer ) { 1306 out.writeByte(CONSTANT_INTEGER); 1307 out.writeInt(((Integer ) value).intValue()); 1308 } else if (value instanceof Float ) { 1309 out.writeByte(CONSTANT_FLOAT); 1310 out.writeFloat(((Float ) value).floatValue()); 1311 } else if (value instanceof Long ) { 1312 out.writeByte(CONSTANT_LONG); 1313 out.writeLong(((Long ) value).longValue()); 1314 } else if (value instanceof Double ) { 1315 out.writeDouble(CONSTANT_DOUBLE); 1316 out.writeDouble(((Double ) value).doubleValue()); 1317 } else { 1318 throw new InternalError ("bogus value entry: " + value); 1319 } 1320 } 1321 } 1322 1323 1338 private static class IndirectEntry extends Entry { 1339 private int tag; 1340 private short index0; 1341 private short index1; 1342 1343 1347 public IndirectEntry(int tag, short index) { 1348 this.tag = tag; 1349 this.index0 = index; 1350 this.index1 = 0; 1351 } 1352 1353 1357 public IndirectEntry(int tag, short index0, short index1) { 1358 this.tag = tag; 1359 this.index0 = index0; 1360 this.index1 = index1; 1361 } 1362 1363 public void write(DataOutputStream out) throws IOException { 1364 out.writeByte(tag); 1365 out.writeShort(index0); 1366 1370 if (tag == CONSTANT_FIELD || 1371 tag == CONSTANT_METHOD || 1372 tag == CONSTANT_INTERFACEMETHOD || 1373 tag == CONSTANT_NAMEANDTYPE) 1374 { 1375 out.writeShort(index1); 1376 } 1377 } 1378 1379 public int hashCode() { 1380 return tag + index0 + index1; 1381 } 1382 1383 public boolean equals(Object obj) { 1384 if (obj instanceof IndirectEntry) { 1385 IndirectEntry other = (IndirectEntry) obj; 1386 if (tag == other.tag && 1387 index0 == other.index0 && index1 == other.index1) 1388 { 1389 return true; 1390 } 1391 } 1392 return false; 1393 } 1394 } 1395 } 1396} 1397 | Popular Tags |