1 19 package org.netbeans.lib.jmi.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.util.*; 26 27 31 public abstract class ClassFileGenerator { 32 33 34 public static final int JAVA_MAGIC = 0xcafebabe; 35 36 37 public static final int JAVA_DEFAULT_VERSION = 45; 38 public static final int JAVA_DEFAULT_MINOR_VERSION = 3; 39 40 41 public static final int CONSTANT_UTF8 = 1; 42 public static final int CONSTANT_INTEGER = 3; 43 public static final int CONSTANT_FLOAT = 4; 44 public static final int CONSTANT_LONG = 5; 45 public static final int CONSTANT_DOUBLE = 6; 46 public static final int CONSTANT_CLASS = 7; 47 public static final int CONSTANT_STRING = 8; 48 public static final int CONSTANT_FIELD = 9; 49 public static final int CONSTANT_METHOD = 10; 50 public static final int CONSTANT_INTERFACEMETHOD = 11; 51 public static final int CONSTANT_NAMEANDTYPE = 12; 52 53 54 public static final int ACC_PUBLIC = 0x00000001; 55 public static final int ACC_PRIVATE = 0x00000002; 56 public static final int ACC_PROTECTED = 0x00000004; 57 public static final int ACC_STATIC = 0x00000008; 58 public static final int ACC_FINAL = 0x00000010; 59 public static final int ACC_SUPER = 0x00000020; 60 public static final int ACC_INTERFACE = 0x00000200; 61 public static final int ACC_ABSTRACT = 0x00000400; 62 63 64 public static final int T_BYTE = 0x00000008; 65 66 67 public static final int opc_aconst_null = 1; 68 public static final int opc_iconst_0 = 3; 69 public static final int opc_iconst_1 = 4; 70 public static final int opc_lconst_0 = 9; 71 public static final int opc_fconst_0 = 11; 72 public static final int opc_dconst_0 = 14; 73 public static final int opc_bipush = 16; 74 public static final int opc_sipush = 17; 75 public static final int opc_ldc = 18; 76 public static final int opc_ldc_w = 19; 77 public static final int opc_iload = 21; 78 public static final int opc_lload = 22; 79 public static final int opc_fload = 23; 80 public static final int opc_dload = 24; 81 public static final int opc_aload = 25; 82 public static final int opc_iload_0 = 26; 83 public static final int opc_lload_0 = 30; 84 public static final int opc_fload_0 = 34; 85 public static final int opc_dload_0 = 38; 86 public static final int opc_aload_0 = 42; 87 public static final int opc_aload_1 = 43; 88 public static final int opc_aaload = 50; 89 public static final int opc_istore = 54; 90 public static final int opc_lstore = 55; 91 public static final int opc_fstore = 56; 92 public static final int opc_dstore = 57; 93 public static final int opc_astore = 58; 94 public static final int opc_istore_0 = 59; 95 public static final int opc_lstore_0 = 63; 96 public static final int opc_fstore_0 = 67; 97 public static final int opc_dstore_0 = 71; 98 public static final int opc_astore_0 = 75; 99 public static final int opc_aastore = 83; 100 public static final int opc_bastore = 84; 101 public static final int opc_pop = 87; 102 public static final int opc_dup = 89; 103 public static final int opc_ifeq = 153; 104 public static final int opc_ifne = 154; 105 public static final int opc_ifle = 158; 106 public static final int opc_if_icmpeq = 159; 107 public static final int opc_if_acmpne = 166; 108 public static final int opc_goto = 167; 109 public static final int opc_jsr = 168; 110 public static final int opc_ret = 169; 111 public static final int opc_ireturn = 172; 112 public static final int opc_lreturn = 173; 113 public static final int opc_freturn = 174; 114 public static final int opc_dreturn = 175; 115 public static final int opc_areturn = 176; 116 public static final int opc_return = 177; 117 public static final int opc_getstatic = 178; 118 public static final int opc_putstatic = 179; 119 public static final int opc_getfield = 180; 120 public static final int opc_putfield = 181; 121 public static final int opc_invokevirtual = 182; 122 public static final int opc_invokespecial = 183; 123 public static final int opc_invokestatic = 184; 124 public static final int opc_invokeinterface = 185; 125 public static final int opc_new = 187; 126 public static final int opc_newarray = 188; 127 public static final int opc_anewarray = 189; 128 public static final int opc_arraylength = 190; 129 public static final int opc_athrow = 191; 130 public static final int opc_checkcast = 192; 131 public static final int opc_instanceof = 193; 132 public static final int opc_wide = 196; 133 public static final int opc_ifnull = 198; 134 135 136 protected String className; 137 138 139 protected int accessFlags; 140 141 142 protected String superclassName; 143 144 145 protected String [] ifaceNames; 146 147 148 protected ConstantPool cp = new ConstantPool(); 149 150 154 protected ClassFileGenerator(String className, String [] interfaces, String superclass, int accessFlags) { 155 this.className = className; 156 this.ifaceNames = interfaces; 157 this.superclassName = superclass; 158 this.accessFlags = accessFlags; 159 } 160 161 165 final protected void generateClassFile(OutputStream stream) { 166 try { 167 MethodInfo[] methods = generateMethods(); 169 FieldInfo[] fields = generateFields(); 170 171 cp.getClass(dotToSlash(className)); 173 cp.getClass(dotToSlash(superclassName)); 174 for (int i = 0; i < ifaceNames.length; i++) 175 cp.getClass(dotToSlash(ifaceNames[i])); 176 cp.setReadOnly(); 177 178 DataOutputStream dout = new DataOutputStream (stream); 180 181 dout.writeInt(JAVA_MAGIC); 183 dout.writeShort(JAVA_DEFAULT_MINOR_VERSION); 185 dout.writeShort(JAVA_DEFAULT_VERSION); 187 188 cp.write(dout); 190 191 dout.writeShort(accessFlags); 193 194 dout.writeShort(cp.getClass(dotToSlash(className))); 196 197 dout.writeShort(cp.getClass(dotToSlash(superclassName))); 199 200 dout.writeShort(ifaceNames.length); 202 for (int i = 0; i < ifaceNames.length; i++) 204 dout.writeShort(cp.getClass(dotToSlash(ifaceNames[i]))); 205 206 dout.writeShort(fields.length); 208 for (int i = 0; i < fields.length; i++) 210 fields[i].write(dout); 211 212 dout.writeShort(methods.length); 214 for (int i = 0 ; i < methods.length; i++) 216 methods[i].write(dout); 217 218 dout.writeShort(0); 220 dout.close(); 221 } catch (IOException e) { 222 throw new InternalError ("unexpected I/O Exception"); } 224 } 225 226 protected abstract MethodInfo[] generateMethods() throws IOException ; 227 protected abstract FieldInfo[] generateFields() throws IOException ; 228 229 234 final protected class FieldInfo { 235 private int accessFlags; 236 private String name; 237 private String descriptor; 238 private Object constValue; 239 240 public FieldInfo(String name, String descriptor, int accessFlags) { 241 this.name = name; 242 this.descriptor = descriptor; 243 this.accessFlags = accessFlags; 244 245 249 cp.getUtf8(name); 250 cp.getUtf8(descriptor); 251 } 252 253 public void setConstValue(Object value) { 254 if ((accessFlags & ACC_STATIC) != 0) { 255 constValue = value; 256 cp.getUtf8("ConstantValue"); cp.getUnknownValue(constValue); 258 } 259 } 260 261 final public void write(DataOutputStream out) throws IOException { 262 266 out.writeShort(accessFlags); 268 out.writeShort(cp.getUtf8(name)); 270 out.writeShort(cp.getUtf8(descriptor)); 272 if (constValue == null) 274 out.writeShort(0); else { 276 out.writeShort(1); 277 out.writeShort(cp.getUtf8("ConstantValue")); out.writeInt(2); 281 out.writeShort(cp.getUnknownValue(constValue)); 283 } 284 } 285 286 public boolean equals(Object o) { 287 if (o instanceof FieldInfo) { 288 return ((FieldInfo) o).name.equalsIgnoreCase(name); 289 } else { 290 return false; 291 } 292 } 293 294 public int hashCode() { 295 return name.toUpperCase(Locale.US).hashCode(); 296 } 297 } 298 299 304 final protected static class ExceptionTableEntry { 305 public short startPc; 306 public short endPc; 307 public short handlerPc; 308 public short catchType; 309 310 public ExceptionTableEntry(short startPc, short endPc, 311 short handlerPc, short catchType) { 312 this.startPc = startPc; 313 this.endPc = endPc; 314 this.handlerPc = handlerPc; 315 this.catchType = catchType; 316 } 317 }; 318 319 324 final protected class MethodInfo { 325 private int accessFlags; 326 private String name; 327 private String descriptor; 328 private ByteArrayOutputStream code = new ByteArrayOutputStream (); 329 private short maxStack; 330 private short maxLocals; 331 private short[] declaredExceptions; 332 private List exceptionTable = new ArrayList(); 333 334 public MethodInfo(String name, String descriptor, int accessFlags) { 335 this.name = name; 336 this.descriptor = descriptor; 337 this.accessFlags = accessFlags; 338 339 343 cp.getUtf8(name); 344 cp.getUtf8(descriptor); 345 } 346 347 public void setDeclaredExceptions(short[] exceptions) { 348 cp.getUtf8("Exceptions"); declaredExceptions = exceptions; 350 } 351 352 public ByteArrayOutputStream getCodeStream() { 353 cp.getUtf8("Code"); return code; 355 } 356 357 public void setMaxStack(short max) { 358 maxStack = max; 359 } 360 361 public void setMaxLocals(short max) { 362 maxLocals = max; 363 } 364 365 public List getExceptionTable() { 366 return exceptionTable; 367 } 368 369 public void write(DataOutputStream out) throws IOException { 370 374 out.writeShort(accessFlags); 376 out.writeShort(cp.getUtf8(name)); 378 out.writeShort(cp.getUtf8(descriptor)); 380 short count = 0; 382 if (code.size() > 0) 383 count++; 384 if (declaredExceptions != null && declaredExceptions.length > 0) 385 count++; 386 out.writeShort(count); 387 388 if (code.size() > 0) { 390 out.writeShort(cp.getUtf8("Code")); out.writeInt(12 + code.size() + 8 * exceptionTable.size()); 394 out.writeShort(maxStack); 396 out.writeShort(maxLocals); 398 out.writeInt(code.size()); 400 code.writeTo(out); 402 out.writeShort(exceptionTable.size()); 404 for (Iterator iter = exceptionTable.iterator(); iter.hasNext();) { 405 ExceptionTableEntry e = (ExceptionTableEntry) iter.next(); 406 out.writeShort(e.startPc); 408 out.writeShort(e.endPc); 410 out.writeShort(e.handlerPc); 412 out.writeShort(e.catchType); 414 } 415 out.writeShort(0); 417 } 418 419 if (declaredExceptions != null && declaredExceptions.length > 0) { 421 out.writeShort(cp.getUtf8("Exceptions")); out.writeInt(2 + 2 * declaredExceptions.length); 425 out.writeShort(declaredExceptions.length); 427 for (int i = 0; i < declaredExceptions.length; i++) 429 out.writeShort(declaredExceptions[i]); 430 } 431 } 432 433 } 434 435 438 439 444 445 protected void code_iload(int lvar, DataOutputStream out) 446 throws IOException { 447 codeLocalLoadStore(lvar, 448 opc_iload, opc_iload_0, out); 449 } 450 451 protected void code_lload(int lvar, DataOutputStream out) 452 throws IOException { 453 codeLocalLoadStore(lvar, 454 opc_lload, opc_lload_0, out); 455 } 456 457 protected void code_fload(int lvar, DataOutputStream out) 458 throws IOException { 459 codeLocalLoadStore(lvar, 460 opc_fload, opc_fload_0, out); 461 } 462 463 protected void code_dload(int lvar, DataOutputStream out) 464 throws IOException { 465 codeLocalLoadStore(lvar, 466 opc_dload, opc_dload_0, out); 467 } 468 469 protected void code_aload(int lvar, DataOutputStream out) 470 throws IOException { 471 codeLocalLoadStore(lvar, 472 opc_aload, opc_aload_0, out); 473 } 474 475 protected void code_istore(int lvar, DataOutputStream out) 476 throws IOException { 477 codeLocalLoadStore(lvar, 478 opc_istore, opc_istore_0, out); 479 } 480 481 protected void code_lstore(int lvar, DataOutputStream out) 482 throws IOException { 483 codeLocalLoadStore(lvar, 484 opc_lstore, opc_lstore_0, out); 485 } 486 487 protected void code_fstore(int lvar, DataOutputStream out) 488 throws IOException { 489 codeLocalLoadStore(lvar, 490 opc_fstore, opc_fstore_0, out); 491 } 492 493 protected void code_dstore(int lvar, DataOutputStream out) 494 throws IOException { 495 codeLocalLoadStore(lvar, 496 opc_dstore, opc_dstore_0, out); 497 } 498 499 protected void code_astore(int lvar, DataOutputStream out) 500 throws IOException { 501 codeLocalLoadStore(lvar, 502 opc_astore, opc_astore_0, out); 503 } 504 505 514 protected void codeLocalLoadStore(int lvar, int opcode, int opcode_0, 515 DataOutputStream out) 516 throws IOException { 517 _assert(lvar >= 0 && lvar <= 0xFFFF); 518 if (lvar <= 3) { 519 out.writeByte(opcode_0 + lvar); 520 } else if (lvar <= 0xFF) { 521 out.writeByte(opcode); 522 out.writeByte(lvar & 0xFF); 523 } else { 524 528 out.writeByte(opc_wide); 529 out.writeByte(opcode); 530 out.writeShort(lvar & 0xFFFF); 531 } 532 } 533 534 539 protected void code_ldc(int index, DataOutputStream out) 540 throws IOException { 541 _assert(index >= 0 && index <= 0xFFFF); 542 if (index <= 0xFF) { 543 out.writeByte(opc_ldc); 544 out.writeByte(index & 0xFF); 545 } else { 546 out.writeByte(opc_ldc_w); 547 out.writeShort(index & 0xFFFF); 548 } 549 } 550 551 557 protected void code_ipush(int value, DataOutputStream out) 558 throws IOException { 559 if (value >= -1 && value <= 5) { 560 out.writeByte(opc_iconst_0 + value); 561 } else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) { 562 out.writeByte(opc_bipush); 563 out.writeByte(value & 0xFF); 564 } else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) { 565 out.writeByte(opc_sipush); 566 out.writeShort(value & 0xFFFF); 567 } else { 568 _assert(false); 569 } 570 } 571 572 protected void codeReturnFieldValue(String className, String fieldName, String descriptor, boolean isStatic, DataOutputStream out) 573 throws IOException { 574 short index = cp.getFieldRef(dotToSlash(className), fieldName, descriptor); 575 _assert(index >= 0); 576 if (isStatic) 577 out.writeByte(opc_getstatic); 578 else { 579 code_aload(0, out); 580 out.writeByte(opc_getfield); 581 } 582 out.writeShort(index); 583 if (descriptor.equals("I") || descriptor.equals("S") || descriptor.equals("C") || descriptor.equals("B") || descriptor.equals("Z")) out.writeByte(opc_ireturn); 586 else if (descriptor.equals("J")) out.writeByte(opc_lreturn); 588 else if (descriptor.equals("F")) out.writeByte(opc_freturn); 590 else if (descriptor.equals("D")) out.writeByte(opc_dreturn); 592 else 593 out.writeByte(opc_areturn); 594 } 595 596 602 protected void codeClassForName(Class cl, DataOutputStream out) 603 throws IOException { 604 code_ldc(cp.getString(cl.getName()), out); 605 606 out.writeByte(opc_invokestatic); 607 out.writeShort(cp.getMethodRef( 608 "java/lang/Class", "forName", "(Ljava/lang/String;)Ljava/lang/Class;")); } 611 614 615 protected static String firstUpper(String text) { 616 try { 617 return text.substring(0, 1).toUpperCase(Locale.US) + text.substring(1); 618 } catch (IndexOutOfBoundsException e) { 619 return ""; } 621 } 622 623 protected static String firstLower(String text) { 624 try { 625 return text.substring(0, 1).toLowerCase(Locale.US) + text.substring(1); 626 } catch (IndexOutOfBoundsException e) { 627 return ""; } 629 } 630 631 634 protected static void _assert(boolean assertion) { 635 if (assertion != true) { 636 throw new InternalError ("assertion failure"); } 638 } 639 640 647 protected static String dotToSlash(String name) { 648 return name.replace('.', '/'); 649 } 650 651 655 protected static String getMethodDescriptor(String [] parameterTypeNames, 656 String returnTypeName) { 657 return getParameterDescriptors(parameterTypeNames) + 658 ((returnTypeName.equals("void")) ? "V" : getFieldType(returnTypeName)); } 660 661 668 protected static String getParameterDescriptors(String [] parameterTypeNames) { 669 StringBuffer desc = new StringBuffer ("("); for (int i = 0; i < parameterTypeNames.length; i++) { 671 desc.append(getFieldType(parameterTypeNames[i])); 672 } 673 desc.append(')'); 674 return desc.toString(); 675 } 676 677 682 protected static String getFieldType(String typeName) { 683 PrimitiveTypeInfo ptInfo = PrimitiveTypeInfo.get(typeName); 684 if (ptInfo != null) 685 return ptInfo.baseTypeString; 686 else if (typeName.endsWith("[]")) return "[" + getFieldType(typeName.substring(0, typeName.length()-2).trim()); else 689 return "L" + dotToSlash(typeName) + ";"; } 691 692 701 protected static int getWordsPerType(String typeName) { 702 if (typeName.equals("long") || typeName.equals("double")) return 2; 704 return 1; 705 } 706 707 712 protected static class PrimitiveTypeInfo { 713 714 715 public String baseTypeString; 716 717 718 public String wrapperClassName; 719 720 721 public String wrapperConstructorDesc; 722 723 724 public String unwrapMethodName; 725 726 727 public String unwrapMethodDesc; 728 729 private static Map table = new HashMap(11); 730 static { 731 table.put("int", new PrimitiveTypeInfo( "I", "java/lang/Integer", "(I)V", "intValue", "()I")); table.put("boolean", new PrimitiveTypeInfo( "Z", "java/lang/Boolean", "(Z)V", "booleanValue", "()Z")); table.put("byte", new PrimitiveTypeInfo( "B", "java/lang/Byte", "(B)V", "byteValue", "()B")); table.put("char", new PrimitiveTypeInfo( "C", "java/lang/Char", "(C)V", "charValue", "()C")); table.put("short", new PrimitiveTypeInfo( "S", "java/lang/Short", "(S)V", "shortValue", "()S")); table.put("long", new PrimitiveTypeInfo( "J", "java/lang/Long", "(J)V", "longValue", "()J")); table.put("float", new PrimitiveTypeInfo( "F", "java/lang/Float", "(F)V", "floatValue", "()F")); table.put("double", new PrimitiveTypeInfo( "D", "java/lang/Double", "(D)V", "doubleValue", "()D")); } 748 749 private PrimitiveTypeInfo(String baseTypeString, 750 String wrapperClassName, 751 String wrapperConstructorDesc, 752 String unwrapMethodName, 753 String unwrapMethodDesc) { 754 this.baseTypeString = baseTypeString; 755 this.wrapperClassName = wrapperClassName; 756 this.wrapperConstructorDesc = wrapperConstructorDesc; 757 this.unwrapMethodName = unwrapMethodName; 758 this.unwrapMethodDesc = unwrapMethodDesc; 759 } 760 761 public static PrimitiveTypeInfo get(String name) { 762 return (PrimitiveTypeInfo) table.get(name); 763 } 764 } 765 766 767 783 protected static class ConstantPool { 784 785 792 private List pool = new ArrayList(32); 793 794 800 private Map map = new HashMap(16); 801 802 803 private boolean readOnly = false; 804 805 808 public short getUtf8(String s) { 809 if (s == null) { 810 throw new NullPointerException (); 811 } 812 return getValue(s); 813 } 814 815 818 public short getInteger(int i) { 819 return getValue(new Integer (i)); 820 } 821 822 825 public short getFloat(float f) { 826 return getValue(new Float (f)); 827 } 828 829 832 public short getLong(long l) { 833 return getValue(new Long (l)); 834 } 835 836 839 public short getDouble(double d) { 840 return getValue(new Double (d)); 841 } 842 843 846 public short getClass(String name) { 847 short utf8Index = getUtf8(name); 848 return getIndirect(new IndirectEntry( 849 CONSTANT_CLASS, utf8Index)); 850 } 851 852 855 public short getString(String s) { 856 short utf8Index = getUtf8(s); 857 return getIndirect(new IndirectEntry( 858 CONSTANT_STRING, utf8Index)); 859 } 860 861 864 public short getFieldRef(String className, 865 String name, String descriptor) { 866 short classIndex = getClass(className); 867 short nameAndTypeIndex = getNameAndType(name, descriptor); 868 return getIndirect(new IndirectEntry( 869 CONSTANT_FIELD, 870 classIndex, nameAndTypeIndex)); 871 } 872 873 876 public short getMethodRef(String className, 877 String name, String descriptor) { 878 short classIndex = getClass(className); 879 short nameAndTypeIndex = getNameAndType(name, descriptor); 880 return getIndirect(new IndirectEntry( 881 CONSTANT_METHOD, 882 classIndex, nameAndTypeIndex)); 883 } 884 885 888 public short getInterfaceMethodRef(String className, String name, 889 String descriptor) { 890 short classIndex = getClass(className); 891 short nameAndTypeIndex = getNameAndType(name, descriptor); 892 return getIndirect(new IndirectEntry( 893 CONSTANT_INTERFACEMETHOD, 894 classIndex, nameAndTypeIndex)); 895 } 896 897 900 public short getNameAndType(String name, String descriptor) { 901 short nameIndex = getUtf8(name); 902 short descriptorIndex = getUtf8(descriptor); 903 return getIndirect(new IndirectEntry( 904 CONSTANT_NAMEANDTYPE, 905 nameIndex, descriptorIndex)); 906 } 907 908 public short getUnknownValue(Object value) { 909 if (value == null) 910 throw new NullPointerException (); 911 if (value instanceof String ) 912 return getString((String )value); 913 if (value instanceof Integer || value instanceof Float || 914 value instanceof Long || value instanceof Double ) 915 return getValue(value); 916 throw new InternalError ("bogus value entry: " + value); } 918 919 926 public void setReadOnly() { 927 readOnly = true; 928 } 929 930 938 public void write(OutputStream out) throws IOException { 939 DataOutputStream dataOut = new DataOutputStream (out); 940 941 dataOut.writeShort(pool.size() + 1); 943 944 for (Iterator iter = pool.iterator(); iter.hasNext();) { 945 Entry e = (Entry) iter.next(); 946 e.write(dataOut); 947 } 948 } 949 950 953 private short addEntry(Entry entry) { 954 pool.add(entry); 955 return (short) pool.size(); 956 } 957 958 969 private short getValue(Object key) { 970 Short index = (Short ) map.get(key); 971 if (index != null) { 972 return index.shortValue(); 973 } else { 974 if (readOnly) { 975 throw new InternalError ( 976 "late constant pool addition: " + key); } 978 short i = addEntry(new ValueEntry(key)); 979 map.put(key, new Short (i)); 980 return i; 981 } 982 } 983 984 988 private short getIndirect(IndirectEntry e) { 989 Short index = (Short ) map.get(e); 990 if (index != null) { 991 return index.shortValue(); 992 } else { 993 if (readOnly) { 994 throw new InternalError ("late constant pool addition"); } 996 short i = addEntry(e); 997 map.put(e, new Short (i)); 998 return i; 999 } 1000 } 1001 1002 1007 private static abstract class Entry { 1008 public abstract void write(DataOutputStream out) 1009 throws IOException ; 1010 } 1011 1012 1020 private static class ValueEntry extends Entry { 1021 private Object value; 1022 1023 public ValueEntry(Object value) { 1024 this.value = value; 1025 } 1026 1027 public void write(DataOutputStream out) throws IOException { 1028 if (value instanceof String ) { 1029 out.writeByte(CONSTANT_UTF8); 1030 out.writeUTF((String ) value); 1031 } else if (value instanceof Integer ) { 1032 out.writeByte(CONSTANT_INTEGER); 1033 out.writeInt(((Integer ) value).intValue()); 1034 } else if (value instanceof Float ) { 1035 out.writeByte(CONSTANT_FLOAT); 1036 out.writeFloat(((Float ) value).floatValue()); 1037 } else if (value instanceof Long ) { 1038 out.writeByte(CONSTANT_LONG); 1039 out.writeLong(((Long ) value).longValue()); 1040 } else if (value instanceof Double ) { 1041 out.writeDouble(CONSTANT_DOUBLE); 1042 out.writeDouble(((Double ) value).doubleValue()); 1043 } else { 1044 throw new InternalError ("bogus value entry: " + value); } 1046 } 1047 } 1048 1049 1064 private static class IndirectEntry extends Entry { 1065 private int tag; 1066 private short index0; 1067 private short index1; 1068 1069 1073 public IndirectEntry(int tag, short index) { 1074 this.tag = tag; 1075 this.index0 = index; 1076 this.index1 = 0; 1077 } 1078 1079 1083 public IndirectEntry(int tag, short index0, short index1) { 1084 this.tag = tag; 1085 this.index0 = index0; 1086 this.index1 = index1; 1087 } 1088 1089 public void write(DataOutputStream out) throws IOException { 1090 out.writeByte(tag); 1091 out.writeShort(index0); 1092 1096 if (tag == CONSTANT_FIELD || 1097 tag == CONSTANT_METHOD || 1098 tag == CONSTANT_INTERFACEMETHOD || 1099 tag == CONSTANT_NAMEANDTYPE) { 1100 out.writeShort(index1); 1101 } 1102 } 1103 1104 public int hashCode() { 1105 return tag + index0 + index1; 1106 } 1107 1108 public boolean equals(Object obj) { 1109 if (obj instanceof IndirectEntry) { 1110 IndirectEntry other = (IndirectEntry) obj; 1111 if (tag == other.tag && 1112 index0 == other.index0 && index1 == other.index1) { 1113 return true; 1114 } 1115 } 1116 return false; 1117 } 1118 } 1119 } 1120} 1121 | Popular Tags |