1 15 16 package javassist; 17 18 import javassist.bytecode.*; 19 import javassist.compiler.Javac; 20 import javassist.compiler.CompileError; 21 import javassist.compiler.ast.ASTree; 22 23 28 public class CtField extends CtMember { 29 protected FieldInfo fieldInfo; 30 31 51 public CtField(CtClass type, String name, CtClass declaring) 52 throws CannotCompileException 53 { 54 this(Descriptor.of(type), name, declaring); 55 } 56 57 74 public CtField(CtField src, CtClass declaring) 75 throws CannotCompileException 76 { 77 this(src.fieldInfo.getDescriptor(), src.fieldInfo.getName(), 78 declaring); 79 } 80 81 private CtField(String typeDesc, String name, CtClass clazz) 82 throws CannotCompileException 83 { 84 super(clazz); 85 next = null; 86 ClassFile cf = clazz.getClassFile2(); 87 if (cf == null) 88 throw new CannotCompileException("bad declaring class: " 89 + clazz.getName()); 90 91 fieldInfo = new FieldInfo(cf.getConstPool(), name, typeDesc); 92 } 93 94 CtField(FieldInfo fi, CtClass clazz) { 95 super(clazz); 96 fieldInfo = fi; 97 next = null; 98 } 99 100 103 public String toString() { 104 return getDeclaringClass().getName() + "." + getName() 105 + ":" + fieldInfo.getDescriptor(); 106 } 107 108 protected void extendToString(StringBuffer buffer) { 109 buffer.append(' '); 110 buffer.append(getName()); 111 buffer.append(' '); 112 buffer.append(fieldInfo.getDescriptor()); 113 } 114 115 117 protected ASTree getInitAST() { return null; } 118 119 121 Initializer getInit() { 122 ASTree tree = getInitAST(); 123 if (tree == null) 124 return null; 125 else 126 return Initializer.byExpr(tree); 127 } 128 129 143 public static CtField make(String src, CtClass declaring) 144 throws CannotCompileException 145 { 146 Javac compiler = new Javac(declaring); 147 try { 148 CtMember obj = compiler.compile(src); 149 if (obj instanceof CtField) 150 return (CtField)obj; } 152 catch (CompileError e) { 153 throw new CannotCompileException(e); 154 } 155 156 throw new CannotCompileException("not a field"); 157 } 158 159 162 public FieldInfo getFieldInfo() { 163 declaringClass.checkModify(); 164 return fieldInfo; 165 } 166 167 170 public FieldInfo getFieldInfo2() { return fieldInfo; } 171 172 175 public CtClass getDeclaringClass() { 176 return super.getDeclaringClass(); 178 } 179 180 183 public String getName() { 184 return fieldInfo.getName(); 185 } 186 187 190 public void setName(String newName) { 191 declaringClass.checkModify(); 192 fieldInfo.setName(newName); 193 } 194 195 200 public int getModifiers() { 201 return AccessFlag.toModifier(fieldInfo.getAccessFlags()); 202 } 203 204 209 public void setModifiers(int mod) { 210 declaringClass.checkModify(); 211 fieldInfo.setAccessFlags(AccessFlag.of(mod)); 212 } 213 214 217 public CtClass getType() throws NotFoundException { 218 return Descriptor.toCtClass(fieldInfo.getDescriptor(), 219 declaringClass.getClassPool()); 220 } 221 222 225 public void setType(CtClass clazz) { 226 declaringClass.checkModify(); 227 fieldInfo.setDescriptor(Descriptor.of(clazz)); 228 } 229 230 244 public Object getConstantValue() { 245 248 int index = fieldInfo.getConstantValue(); 249 if (index == 0) 250 return null; 251 252 ConstPool cp = fieldInfo.getConstPool(); 253 switch (cp.getTag(index)) { 254 case ConstPool.CONST_Long : 255 return new Long (cp.getLongInfo(index)); 256 case ConstPool.CONST_Float : 257 return new Float (cp.getFloatInfo(index)); 258 case ConstPool.CONST_Double : 259 return new Double (cp.getDoubleInfo(index)); 260 case ConstPool.CONST_Integer : 261 int value = cp.getIntegerInfo(index); 262 if ("Z".equals(fieldInfo.getDescriptor())) 264 return new Boolean (value != 0); 265 else 266 return new Integer (value); 267 case ConstPool.CONST_String : 268 return cp.getStringInfo(index); 269 default : 270 throw new RuntimeException ("bad tag: " + cp.getTag(index) 271 + " at " + index); 272 } 273 } 274 275 282 public byte[] getAttribute(String name) { 283 AttributeInfo ai = fieldInfo.getAttribute(name); 284 if (ai == null) 285 return null; 286 else 287 return ai.get(); 288 } 289 290 296 public void setAttribute(String name, byte[] data) { 297 declaringClass.checkModify(); 298 fieldInfo.addAttribute(new AttributeInfo(fieldInfo.getConstPool(), 299 name, data)); 300 } 301 302 304 317 public static abstract class Initializer { 318 322 public static Initializer constant(int i) { 323 return new IntInitializer(i); 324 } 325 326 330 public static Initializer constant(long l) { 331 return new LongInitializer(l); 332 } 333 334 338 public static Initializer constant(double d) { 339 return new DoubleInitializer(d); 340 } 341 342 346 public static Initializer constant(String s) { 347 return new StringInitializer(s); 348 } 349 350 364 public static Initializer byParameter(int nth) { 365 ParamInitializer i = new ParamInitializer(); 366 i.nthParam = nth; 367 return i; 368 } 369 370 385 public static Initializer byNew(CtClass objectType) { 386 NewInitializer i = new NewInitializer(); 387 i.objectType = objectType; 388 i.stringParams = null; 389 i.withConstructorParams = false; 390 return i; 391 } 392 393 412 public static Initializer byNew(CtClass objectType, 413 String [] stringParams) { 414 NewInitializer i = new NewInitializer(); 415 i.objectType = objectType; 416 i.stringParams = stringParams; 417 i.withConstructorParams = false; 418 return i; 419 } 420 421 442 public static Initializer byNewWithParams(CtClass objectType) { 443 NewInitializer i = new NewInitializer(); 444 i.objectType = objectType; 445 i.stringParams = null; 446 i.withConstructorParams = true; 447 return i; 448 } 449 450 472 public static Initializer byNewWithParams(CtClass objectType, 473 String [] stringParams) { 474 NewInitializer i = new NewInitializer(); 475 i.objectType = objectType; 476 i.stringParams = stringParams; 477 i.withConstructorParams = true; 478 return i; 479 } 480 481 501 public static Initializer byCall(CtClass methodClass, 502 String methodName) { 503 MethodInitializer i = new MethodInitializer(); 504 i.objectType = methodClass; 505 i.methodName = methodName; 506 i.stringParams = null; 507 i.withConstructorParams = false; 508 return i; 509 } 510 511 535 public static Initializer byCall(CtClass methodClass, 536 String methodName, 537 String [] stringParams) { 538 MethodInitializer i = new MethodInitializer(); 539 i.objectType = methodClass; 540 i.methodName = methodName; 541 i.stringParams = stringParams; 542 i.withConstructorParams = false; 543 return i; 544 } 545 546 569 public static Initializer byCallWithParams(CtClass methodClass, 570 String methodName) { 571 MethodInitializer i = new MethodInitializer(); 572 i.objectType = methodClass; 573 i.methodName = methodName; 574 i.stringParams = null; 575 i.withConstructorParams = true; 576 return i; 577 } 578 579 606 public static Initializer byCallWithParams(CtClass methodClass, 607 String methodName, String [] stringParams) { 608 MethodInitializer i = new MethodInitializer(); 609 i.objectType = methodClass; 610 i.methodName = methodName; 611 i.stringParams = stringParams; 612 i.withConstructorParams = true; 613 return i; 614 } 615 616 624 public static Initializer byNewArray(CtClass type, int size) 625 throws NotFoundException 626 { 627 return new ArrayInitializer(type.getComponentType(), size); 628 } 629 630 639 public static Initializer byNewArray(CtClass type, int[] sizes) { 640 return new MultiArrayInitializer(type, sizes); 641 } 642 643 648 public static Initializer byExpr(String source) { 649 return new CodeInitializer(source); 650 } 651 652 static Initializer byExpr(ASTree source) { 653 return new PtreeInitializer(source); 654 } 655 656 void check(CtClass type) throws CannotCompileException {} 659 660 abstract int compile(CtClass type, String name, Bytecode code, 662 CtClass[] parameters, Javac drv) 663 throws CannotCompileException; 664 665 abstract int compileIfStatic(CtClass type, String name, 667 Bytecode code, Javac drv) throws CannotCompileException; 668 } 669 670 static abstract class CodeInitializer0 extends Initializer { 671 abstract void compileExpr(Javac drv) throws CompileError; 672 673 int compile(CtClass type, String name, Bytecode code, 674 CtClass[] parameters, Javac drv) 675 throws CannotCompileException 676 { 677 try { 678 code.addAload(0); 679 compileExpr(drv); 680 code.addPutfield(Bytecode.THIS, name, Descriptor.of(type)); 681 return code.getMaxStack(); 682 } 683 catch (CompileError e) { 684 throw new CannotCompileException(e); 685 } 686 } 687 688 int compileIfStatic(CtClass type, String name, Bytecode code, 689 Javac drv) throws CannotCompileException 690 { 691 try { 692 compileExpr(drv); 693 code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type)); 694 return code.getMaxStack(); 695 } 696 catch (CompileError e) { 697 throw new CannotCompileException(e); 698 } 699 } 700 } 701 702 static class CodeInitializer extends CodeInitializer0 { 703 private String expression; 704 705 CodeInitializer(String expr) { expression = expr; } 706 707 void compileExpr(Javac drv) throws CompileError { 708 drv.compileExpr(expression); 709 } 710 } 711 712 static class PtreeInitializer extends CodeInitializer0 { 713 private ASTree expression; 714 715 PtreeInitializer(ASTree expr) { expression = expr; } 716 717 void compileExpr(Javac drv) throws CompileError { 718 drv.compileExpr(expression); 719 } 720 } 721 722 726 static class ParamInitializer extends Initializer { 727 int nthParam; 728 729 ParamInitializer() {} 730 731 int compile(CtClass type, String name, Bytecode code, 732 CtClass[] parameters, Javac drv) 733 throws CannotCompileException 734 { 735 if (parameters != null && nthParam < parameters.length) { 736 code.addAload(0); 737 int nth = nthParamToLocal(nthParam, parameters, false); 738 int s = code.addLoad(nth, type) + 1; 739 code.addPutfield(Bytecode.THIS, name, Descriptor.of(type)); 740 return s; } 742 else 743 return 0; } 745 746 754 static int nthParamToLocal(int nth, CtClass[] params, 755 boolean isStatic) { 756 CtClass longType = CtClass.longType; 757 CtClass doubleType = CtClass.doubleType; 758 int k; 759 if (isStatic) 760 k = 0; 761 else 762 k = 1; 764 for (int i = 0; i < nth; ++i) { 765 CtClass type = params[i]; 766 if (type == longType || type == doubleType) 767 k += 2; 768 else 769 ++k; 770 } 771 772 return k; 773 } 774 775 int compileIfStatic(CtClass type, String name, Bytecode code, 776 Javac drv) throws CannotCompileException 777 { 778 return 0; 779 } 780 } 781 782 785 static class NewInitializer extends Initializer { 786 CtClass objectType; 787 String [] stringParams; 788 boolean withConstructorParams; 789 790 NewInitializer() {} 791 792 796 int compile(CtClass type, String name, Bytecode code, 797 CtClass[] parameters, Javac drv) 798 throws CannotCompileException 799 { 800 int stacksize; 801 802 code.addAload(0); 803 code.addNew(objectType); 804 code.add(Bytecode.DUP); 805 code.addAload(0); 806 807 if (stringParams == null) 808 stacksize = 4; 809 else 810 stacksize = compileStringParameter(code) + 4; 811 812 if (withConstructorParams) 813 stacksize += CtNewWrappedMethod.compileParameterList(code, 814 parameters, 1); 815 816 code.addInvokespecial(objectType, "<init>", getDescriptor()); 817 code.addPutfield(Bytecode.THIS, name, Descriptor.of(type)); 818 return stacksize; 819 } 820 821 private String getDescriptor() { 822 final String desc3 823 = "(Ljava/lang/Object;[Ljava/lang/String;[Ljava/lang/Object;)V"; 824 825 if (stringParams == null) 826 if (withConstructorParams) 827 return "(Ljava/lang/Object;[Ljava/lang/Object;)V"; 828 else 829 return "(Ljava/lang/Object;)V"; 830 else 831 if (withConstructorParams) 832 return desc3; 833 else 834 return "(Ljava/lang/Object;[Ljava/lang/String;)V"; 835 } 836 837 840 int compileIfStatic(CtClass type, String name, Bytecode code, 841 Javac drv) throws CannotCompileException 842 { 843 String desc; 844 845 code.addNew(objectType); 846 code.add(Bytecode.DUP); 847 848 int stacksize = 2; 849 if (stringParams == null) 850 desc = "()V"; 851 else { 852 desc = "([Ljava/lang/String;)V"; 853 stacksize += compileStringParameter(code); 854 } 855 856 code.addInvokespecial(objectType, "<init>", desc); 857 code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type)); 858 return stacksize; 859 } 860 861 protected final int compileStringParameter(Bytecode code) 862 throws CannotCompileException 863 { 864 int nparam = stringParams.length; 865 code.addIconst(nparam); 866 code.addAnewarray("java.lang.String"); 867 for (int j = 0; j < nparam; ++j) { 868 code.add(Bytecode.DUP); code.addIconst(j); code.addLdc(stringParams[j]); code.add(Bytecode.AASTORE); } 873 874 return 4; 875 } 876 877 } 878 879 882 static class MethodInitializer extends NewInitializer { 883 String methodName; 884 886 MethodInitializer() {} 887 888 892 int compile(CtClass type, String name, Bytecode code, 893 CtClass[] parameters, Javac drv) 894 throws CannotCompileException 895 { 896 int stacksize; 897 898 code.addAload(0); 899 code.addAload(0); 900 901 if (stringParams == null) 902 stacksize = 2; 903 else 904 stacksize = compileStringParameter(code) + 2; 905 906 if (withConstructorParams) 907 stacksize += CtNewWrappedMethod.compileParameterList(code, 908 parameters, 1); 909 910 String typeDesc = Descriptor.of(type); 911 String mDesc = getDescriptor() + typeDesc; 912 code.addInvokestatic(objectType, methodName, mDesc); 913 code.addPutfield(Bytecode.THIS, name, typeDesc); 914 return stacksize; 915 } 916 917 private String getDescriptor() { 918 final String desc3 919 = "(Ljava/lang/Object;[Ljava/lang/String;[Ljava/lang/Object;)"; 920 921 if (stringParams == null) 922 if (withConstructorParams) 923 return "(Ljava/lang/Object;[Ljava/lang/Object;)"; 924 else 925 return "(Ljava/lang/Object;)"; 926 else 927 if (withConstructorParams) 928 return desc3; 929 else 930 return "(Ljava/lang/Object;[Ljava/lang/String;)"; 931 } 932 933 936 int compileIfStatic(CtClass type, String name, Bytecode code, 937 Javac drv) throws CannotCompileException 938 { 939 String desc; 940 941 int stacksize = 1; 942 if (stringParams == null) 943 desc = "()"; 944 else { 945 desc = "([Ljava/lang/String;)"; 946 stacksize += compileStringParameter(code); 947 } 948 949 String typeDesc = Descriptor.of(type); 950 code.addInvokestatic(objectType, methodName, desc + typeDesc); 951 code.addPutstatic(Bytecode.THIS, name, typeDesc); 952 return stacksize; 953 } 954 } 955 956 static class IntInitializer extends Initializer { 957 int value; 958 959 IntInitializer(int v) { value = v; } 960 961 void check(CtClass type) throws CannotCompileException { 962 if (type != CtClass.intType) 963 throw new CannotCompileException("type mismatch"); 964 } 965 966 int compile(CtClass type, String name, Bytecode code, 967 CtClass[] parameters, Javac drv) 968 throws CannotCompileException 969 { 970 code.addAload(0); 971 code.addIconst(value); 972 code.addPutfield(Bytecode.THIS, name, Descriptor.of(type)); 973 return 2; } 975 976 int compileIfStatic(CtClass type, String name, Bytecode code, 977 Javac drv) throws CannotCompileException 978 { 979 code.addIconst(value); 980 code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type)); 981 return 1; } 983 } 984 985 static class LongInitializer extends Initializer { 986 long value; 987 988 LongInitializer(long v) { value = v; } 989 990 void check(CtClass type) throws CannotCompileException { 991 if (type != CtClass.longType) 992 throw new CannotCompileException("type mismatch"); 993 } 994 995 int compile(CtClass type, String name, Bytecode code, 996 CtClass[] parameters, Javac drv) 997 throws CannotCompileException 998 { 999 code.addAload(0); 1000 code.addLdc2w(value); 1001 code.addPutfield(Bytecode.THIS, name, Descriptor.of(type)); 1002 return 3; } 1004 1005 int compileIfStatic(CtClass type, String name, Bytecode code, 1006 Javac drv) throws CannotCompileException 1007 { 1008 code.addLdc2w(value); 1009 code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type)); 1010 return 2; } 1012 } 1013 1014 static class DoubleInitializer extends Initializer { 1015 double value; 1016 1017 DoubleInitializer(double v) { value = v; } 1018 1019 void check(CtClass type) throws CannotCompileException { 1020 if (type != CtClass.doubleType) 1021 throw new CannotCompileException("type mismatch"); 1022 } 1023 1024 int compile(CtClass type, String name, Bytecode code, 1025 CtClass[] parameters, Javac drv) 1026 throws CannotCompileException 1027 { 1028 code.addAload(0); 1029 code.addLdc2w(value); 1030 code.addPutfield(Bytecode.THIS, name, Descriptor.of(type)); 1031 return 3; } 1033 1034 int compileIfStatic(CtClass type, String name, Bytecode code, 1035 Javac drv) throws CannotCompileException 1036 { 1037 code.addLdc2w(value); 1038 code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type)); 1039 return 2; } 1041 } 1042 1043 static class StringInitializer extends Initializer { 1044 String value; 1045 1046 StringInitializer(String v) { value = v; } 1047 1048 void check(CtClass type) throws CannotCompileException { 1049 if (!type.getName().equals("java.lang.String")) 1050 throw new CannotCompileException("type mismatch"); 1051 } 1052 1053 int compile(CtClass type, String name, Bytecode code, 1054 CtClass[] parameters, Javac drv) 1055 throws CannotCompileException 1056 { 1057 code.addAload(0); 1058 code.addLdc(value); 1059 code.addPutfield(Bytecode.THIS, name, Descriptor.of(type)); 1060 return 2; } 1062 1063 int compileIfStatic(CtClass type, String name, Bytecode code, 1064 Javac drv) throws CannotCompileException 1065 { 1066 code.addLdc(value); 1067 code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type)); 1068 return 1; } 1070 } 1071 1072 static class ArrayInitializer extends Initializer { 1073 CtClass type; 1074 int size; 1075 1076 ArrayInitializer(CtClass t, int s) { type = t; size = s; } 1077 1078 private void addNewarray(Bytecode code) { 1079 if (type.isPrimitive()) 1080 code.addNewarray(((CtPrimitiveType)type).getArrayType(), 1081 size); 1082 else 1083 code.addAnewarray(type, size); 1084 } 1085 1086 int compile(CtClass type, String name, Bytecode code, 1087 CtClass[] parameters, Javac drv) 1088 throws CannotCompileException 1089 { 1090 code.addAload(0); 1091 addNewarray(code); 1092 code.addPutfield(Bytecode.THIS, name, Descriptor.of(type)); 1093 return 2; } 1095 1096 int compileIfStatic(CtClass type, String name, Bytecode code, 1097 Javac drv) throws CannotCompileException 1098 { 1099 addNewarray(code); 1100 code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type)); 1101 return 1; } 1103 } 1104 1105 static class MultiArrayInitializer extends Initializer { 1106 CtClass type; 1107 int[] dim; 1108 1109 MultiArrayInitializer(CtClass t, int[] d) { type = t; dim = d; } 1110 1111 void check(CtClass type) throws CannotCompileException { 1112 if (!type.isArray()) 1113 throw new CannotCompileException("type mismatch"); 1114 } 1115 1116 int compile(CtClass type, String name, Bytecode code, 1117 CtClass[] parameters, Javac drv) 1118 throws CannotCompileException 1119 { 1120 code.addAload(0); 1121 int s = code.addMultiNewarray(type, dim); 1122 code.addPutfield(Bytecode.THIS, name, Descriptor.of(type)); 1123 return s + 1; } 1125 1126 int compileIfStatic(CtClass type, String name, Bytecode code, 1127 Javac drv) throws CannotCompileException 1128 { 1129 int s = code.addMultiNewarray(type, dim); 1130 code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type)); 1131 return s; } 1133 } 1134} 1135 | Popular Tags |