1*f1fbf3c2SXin Li /* 2*f1fbf3c2SXin Li * Javassist, a Java-bytecode translator toolkit. 3*f1fbf3c2SXin Li * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved. 4*f1fbf3c2SXin Li * 5*f1fbf3c2SXin Li * The contents of this file are subject to the Mozilla Public License Version 6*f1fbf3c2SXin Li * 1.1 (the "License"); you may not use this file except in compliance with 7*f1fbf3c2SXin Li * the License. Alternatively, the contents of this file may be used under 8*f1fbf3c2SXin Li * the terms of the GNU Lesser General Public License Version 2.1 or later, 9*f1fbf3c2SXin Li * or the Apache License Version 2.0. 10*f1fbf3c2SXin Li * 11*f1fbf3c2SXin Li * Software distributed under the License is distributed on an "AS IS" basis, 12*f1fbf3c2SXin Li * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13*f1fbf3c2SXin Li * for the specific language governing rights and limitations under the 14*f1fbf3c2SXin Li * License. 15*f1fbf3c2SXin Li */ 16*f1fbf3c2SXin Li 17*f1fbf3c2SXin Li package javassist; 18*f1fbf3c2SXin Li 19*f1fbf3c2SXin Li import java.util.List; 20*f1fbf3c2SXin Li 21*f1fbf3c2SXin Li import javassist.bytecode.AccessFlag; 22*f1fbf3c2SXin Li import javassist.bytecode.AnnotationsAttribute; 23*f1fbf3c2SXin Li import javassist.bytecode.AttributeInfo; 24*f1fbf3c2SXin Li import javassist.bytecode.Bytecode; 25*f1fbf3c2SXin Li import javassist.bytecode.ClassFile; 26*f1fbf3c2SXin Li import javassist.bytecode.ConstPool; 27*f1fbf3c2SXin Li import javassist.bytecode.Descriptor; 28*f1fbf3c2SXin Li import javassist.bytecode.FieldInfo; 29*f1fbf3c2SXin Li import javassist.bytecode.SignatureAttribute; 30*f1fbf3c2SXin Li import javassist.compiler.CompileError; 31*f1fbf3c2SXin Li import javassist.compiler.Javac; 32*f1fbf3c2SXin Li import javassist.compiler.SymbolTable; 33*f1fbf3c2SXin Li import javassist.compiler.ast.ASTree; 34*f1fbf3c2SXin Li import javassist.compiler.ast.DoubleConst; 35*f1fbf3c2SXin Li import javassist.compiler.ast.IntConst; 36*f1fbf3c2SXin Li import javassist.compiler.ast.StringL; 37*f1fbf3c2SXin Li 38*f1fbf3c2SXin Li /** 39*f1fbf3c2SXin Li * An instance of CtField represents a field. 40*f1fbf3c2SXin Li * 41*f1fbf3c2SXin Li * @see CtClass#getDeclaredFields() 42*f1fbf3c2SXin Li */ 43*f1fbf3c2SXin Li public class CtField extends CtMember { 44*f1fbf3c2SXin Li static final String javaLangString = "java.lang.String"; 45*f1fbf3c2SXin Li 46*f1fbf3c2SXin Li protected FieldInfo fieldInfo; 47*f1fbf3c2SXin Li 48*f1fbf3c2SXin Li /** 49*f1fbf3c2SXin Li * Creates a <code>CtField</code> object. 50*f1fbf3c2SXin Li * The created field must be added to a class 51*f1fbf3c2SXin Li * with <code>CtClass.addField()</code>. 52*f1fbf3c2SXin Li * An initial value of the field is specified 53*f1fbf3c2SXin Li * by a <code>CtField.Initializer</code> object. 54*f1fbf3c2SXin Li * 55*f1fbf3c2SXin Li * <p>If getter and setter methods are needed, 56*f1fbf3c2SXin Li * call <code>CtNewMethod.getter()</code> and 57*f1fbf3c2SXin Li * <code>CtNewMethod.setter()</code>. 58*f1fbf3c2SXin Li * 59*f1fbf3c2SXin Li * @param type field type 60*f1fbf3c2SXin Li * @param name field name 61*f1fbf3c2SXin Li * @param declaring the class to which the field will be added. 62*f1fbf3c2SXin Li * 63*f1fbf3c2SXin Li * @see CtClass#addField(CtField) 64*f1fbf3c2SXin Li * @see CtNewMethod#getter(String,CtField) 65*f1fbf3c2SXin Li * @see CtNewMethod#setter(String,CtField) 66*f1fbf3c2SXin Li * @see CtField.Initializer 67*f1fbf3c2SXin Li */ CtField(CtClass type, String name, CtClass declaring)68*f1fbf3c2SXin Li public CtField(CtClass type, String name, CtClass declaring) 69*f1fbf3c2SXin Li throws CannotCompileException 70*f1fbf3c2SXin Li { 71*f1fbf3c2SXin Li this(Descriptor.of(type), name, declaring); 72*f1fbf3c2SXin Li } 73*f1fbf3c2SXin Li 74*f1fbf3c2SXin Li /** 75*f1fbf3c2SXin Li * Creates a copy of the given field. 76*f1fbf3c2SXin Li * The created field must be added to a class 77*f1fbf3c2SXin Li * with <code>CtClass.addField()</code>. 78*f1fbf3c2SXin Li * An initial value of the field is specified 79*f1fbf3c2SXin Li * by a <code>CtField.Initializer</code> object. 80*f1fbf3c2SXin Li * 81*f1fbf3c2SXin Li * <p>If getter and setter methods are needed, 82*f1fbf3c2SXin Li * call <code>CtNewMethod.getter()</code> and 83*f1fbf3c2SXin Li * <code>CtNewMethod.setter()</code>. 84*f1fbf3c2SXin Li * 85*f1fbf3c2SXin Li * @param src the original field 86*f1fbf3c2SXin Li * @param declaring the class to which the field will be added. 87*f1fbf3c2SXin Li * @see CtNewMethod#getter(String,CtField) 88*f1fbf3c2SXin Li * @see CtNewMethod#setter(String,CtField) 89*f1fbf3c2SXin Li * @see CtField.Initializer 90*f1fbf3c2SXin Li */ CtField(CtField src, CtClass declaring)91*f1fbf3c2SXin Li public CtField(CtField src, CtClass declaring) 92*f1fbf3c2SXin Li throws CannotCompileException 93*f1fbf3c2SXin Li { 94*f1fbf3c2SXin Li this(src.fieldInfo.getDescriptor(), src.fieldInfo.getName(), 95*f1fbf3c2SXin Li declaring); 96*f1fbf3c2SXin Li FieldInfo fi = fieldInfo; 97*f1fbf3c2SXin Li fi.setAccessFlags(src.fieldInfo.getAccessFlags()); 98*f1fbf3c2SXin Li ConstPool cp = fi.getConstPool(); 99*f1fbf3c2SXin Li List<AttributeInfo> attributes = src.fieldInfo.getAttributes(); 100*f1fbf3c2SXin Li for (AttributeInfo ainfo : attributes) 101*f1fbf3c2SXin Li fi.addAttribute(ainfo.copy(cp, null)); 102*f1fbf3c2SXin Li } 103*f1fbf3c2SXin Li CtField(String typeDesc, String name, CtClass clazz)104*f1fbf3c2SXin Li private CtField(String typeDesc, String name, CtClass clazz) 105*f1fbf3c2SXin Li throws CannotCompileException 106*f1fbf3c2SXin Li { 107*f1fbf3c2SXin Li super(clazz); 108*f1fbf3c2SXin Li ClassFile cf = clazz.getClassFile2(); 109*f1fbf3c2SXin Li if (cf == null) 110*f1fbf3c2SXin Li throw new CannotCompileException("bad declaring class: " 111*f1fbf3c2SXin Li + clazz.getName()); 112*f1fbf3c2SXin Li 113*f1fbf3c2SXin Li fieldInfo = new FieldInfo(cf.getConstPool(), name, typeDesc); 114*f1fbf3c2SXin Li } 115*f1fbf3c2SXin Li CtField(FieldInfo fi, CtClass clazz)116*f1fbf3c2SXin Li CtField(FieldInfo fi, CtClass clazz) { 117*f1fbf3c2SXin Li super(clazz); 118*f1fbf3c2SXin Li fieldInfo = fi; 119*f1fbf3c2SXin Li } 120*f1fbf3c2SXin Li 121*f1fbf3c2SXin Li /** 122*f1fbf3c2SXin Li * Returns a String representation of the object. 123*f1fbf3c2SXin Li */ 124*f1fbf3c2SXin Li @Override toString()125*f1fbf3c2SXin Li public String toString() { 126*f1fbf3c2SXin Li return getDeclaringClass().getName() + "." + getName() 127*f1fbf3c2SXin Li + ":" + fieldInfo.getDescriptor(); 128*f1fbf3c2SXin Li } 129*f1fbf3c2SXin Li 130*f1fbf3c2SXin Li @Override extendToString(StringBuffer buffer)131*f1fbf3c2SXin Li protected void extendToString(StringBuffer buffer) { 132*f1fbf3c2SXin Li buffer.append(' '); 133*f1fbf3c2SXin Li buffer.append(getName()); 134*f1fbf3c2SXin Li buffer.append(' '); 135*f1fbf3c2SXin Li buffer.append(fieldInfo.getDescriptor()); 136*f1fbf3c2SXin Li } 137*f1fbf3c2SXin Li 138*f1fbf3c2SXin Li /* Javac.CtFieldWithInit overrides. */ getInitAST()139*f1fbf3c2SXin Li protected ASTree getInitAST() { return null; } 140*f1fbf3c2SXin Li 141*f1fbf3c2SXin Li /* Called by CtClassType.addField(). */ getInit()142*f1fbf3c2SXin Li Initializer getInit() { 143*f1fbf3c2SXin Li ASTree tree = getInitAST(); 144*f1fbf3c2SXin Li if (tree == null) 145*f1fbf3c2SXin Li return null; 146*f1fbf3c2SXin Li return Initializer.byExpr(tree); 147*f1fbf3c2SXin Li } 148*f1fbf3c2SXin Li 149*f1fbf3c2SXin Li /** 150*f1fbf3c2SXin Li * Compiles the given source code and creates a field. 151*f1fbf3c2SXin Li * Examples of the source code are: 152*f1fbf3c2SXin Li * 153*f1fbf3c2SXin Li * <pre> 154*f1fbf3c2SXin Li * "public String name;" 155*f1fbf3c2SXin Li * "public int k = 3;"</pre> 156*f1fbf3c2SXin Li * 157*f1fbf3c2SXin Li * <p>Note that the source code ends with <code>';'</code> 158*f1fbf3c2SXin Li * (semicolon). 159*f1fbf3c2SXin Li * 160*f1fbf3c2SXin Li * @param src the source text. 161*f1fbf3c2SXin Li * @param declaring the class to which the created field is added. 162*f1fbf3c2SXin Li */ make(String src, CtClass declaring)163*f1fbf3c2SXin Li public static CtField make(String src, CtClass declaring) 164*f1fbf3c2SXin Li throws CannotCompileException 165*f1fbf3c2SXin Li { 166*f1fbf3c2SXin Li Javac compiler = new Javac(declaring); 167*f1fbf3c2SXin Li try { 168*f1fbf3c2SXin Li CtMember obj = compiler.compile(src); 169*f1fbf3c2SXin Li if (obj instanceof CtField) 170*f1fbf3c2SXin Li return (CtField)obj; // an instance of Javac.CtFieldWithInit 171*f1fbf3c2SXin Li } 172*f1fbf3c2SXin Li catch (CompileError e) { 173*f1fbf3c2SXin Li throw new CannotCompileException(e); 174*f1fbf3c2SXin Li } 175*f1fbf3c2SXin Li 176*f1fbf3c2SXin Li throw new CannotCompileException("not a field"); 177*f1fbf3c2SXin Li } 178*f1fbf3c2SXin Li 179*f1fbf3c2SXin Li /** 180*f1fbf3c2SXin Li * Returns the FieldInfo representing the field in the class file. 181*f1fbf3c2SXin Li */ getFieldInfo()182*f1fbf3c2SXin Li public FieldInfo getFieldInfo() { 183*f1fbf3c2SXin Li declaringClass.checkModify(); 184*f1fbf3c2SXin Li return fieldInfo; 185*f1fbf3c2SXin Li } 186*f1fbf3c2SXin Li 187*f1fbf3c2SXin Li /** 188*f1fbf3c2SXin Li * Returns the FieldInfo representing the field in the class 189*f1fbf3c2SXin Li * file (read only). 190*f1fbf3c2SXin Li * Normal applications do not need calling this method. Use 191*f1fbf3c2SXin Li * <code>getFieldInfo()</code>. 192*f1fbf3c2SXin Li * 193*f1fbf3c2SXin Li * <p>The <code>FieldInfo</code> object obtained by this method 194*f1fbf3c2SXin Li * is read only. Changes to this object might not be reflected 195*f1fbf3c2SXin Li * on a class file generated by <code>toBytecode()</code>, 196*f1fbf3c2SXin Li * <code>toClass()</code>, etc in <code>CtClass</code>. 197*f1fbf3c2SXin Li * 198*f1fbf3c2SXin Li * <p>This method is available even if the <code>CtClass</code> 199*f1fbf3c2SXin Li * containing this field is frozen. However, if the class is 200*f1fbf3c2SXin Li * frozen, the <code>FieldInfo</code> might be also pruned. 201*f1fbf3c2SXin Li * 202*f1fbf3c2SXin Li * @see #getFieldInfo() 203*f1fbf3c2SXin Li * @see CtClass#isFrozen() 204*f1fbf3c2SXin Li * @see CtClass#prune() 205*f1fbf3c2SXin Li */ getFieldInfo2()206*f1fbf3c2SXin Li public FieldInfo getFieldInfo2() { return fieldInfo; } 207*f1fbf3c2SXin Li 208*f1fbf3c2SXin Li /** 209*f1fbf3c2SXin Li * Returns the class declaring the field. 210*f1fbf3c2SXin Li */ 211*f1fbf3c2SXin Li @Override getDeclaringClass()212*f1fbf3c2SXin Li public CtClass getDeclaringClass() { 213*f1fbf3c2SXin Li // this is redundant but for javadoc. 214*f1fbf3c2SXin Li return super.getDeclaringClass(); 215*f1fbf3c2SXin Li } 216*f1fbf3c2SXin Li 217*f1fbf3c2SXin Li /** 218*f1fbf3c2SXin Li * Returns the name of the field. 219*f1fbf3c2SXin Li */ 220*f1fbf3c2SXin Li @Override getName()221*f1fbf3c2SXin Li public String getName() { 222*f1fbf3c2SXin Li return fieldInfo.getName(); 223*f1fbf3c2SXin Li } 224*f1fbf3c2SXin Li 225*f1fbf3c2SXin Li /** 226*f1fbf3c2SXin Li * Changes the name of the field. 227*f1fbf3c2SXin Li */ setName(String newName)228*f1fbf3c2SXin Li public void setName(String newName) { 229*f1fbf3c2SXin Li declaringClass.checkModify(); 230*f1fbf3c2SXin Li fieldInfo.setName(newName); 231*f1fbf3c2SXin Li } 232*f1fbf3c2SXin Li 233*f1fbf3c2SXin Li /** 234*f1fbf3c2SXin Li * Returns the encoded modifiers of the field. 235*f1fbf3c2SXin Li * 236*f1fbf3c2SXin Li * @see Modifier 237*f1fbf3c2SXin Li */ 238*f1fbf3c2SXin Li @Override getModifiers()239*f1fbf3c2SXin Li public int getModifiers() { 240*f1fbf3c2SXin Li return AccessFlag.toModifier(fieldInfo.getAccessFlags()); 241*f1fbf3c2SXin Li } 242*f1fbf3c2SXin Li 243*f1fbf3c2SXin Li /** 244*f1fbf3c2SXin Li * Sets the encoded modifiers of the field. 245*f1fbf3c2SXin Li * 246*f1fbf3c2SXin Li * @see Modifier 247*f1fbf3c2SXin Li */ 248*f1fbf3c2SXin Li @Override setModifiers(int mod)249*f1fbf3c2SXin Li public void setModifiers(int mod) { 250*f1fbf3c2SXin Li declaringClass.checkModify(); 251*f1fbf3c2SXin Li fieldInfo.setAccessFlags(AccessFlag.of(mod)); 252*f1fbf3c2SXin Li } 253*f1fbf3c2SXin Li 254*f1fbf3c2SXin Li /** 255*f1fbf3c2SXin Li * Returns true if the class has the specified annotation type. 256*f1fbf3c2SXin Li * 257*f1fbf3c2SXin Li * @param typeName the name of annotation type. 258*f1fbf3c2SXin Li * @return <code>true</code> if the annotation is found, otherwise <code>false</code>. 259*f1fbf3c2SXin Li * @since 3.21 260*f1fbf3c2SXin Li */ 261*f1fbf3c2SXin Li @Override hasAnnotation(String typeName)262*f1fbf3c2SXin Li public boolean hasAnnotation(String typeName) { 263*f1fbf3c2SXin Li FieldInfo fi = getFieldInfo2(); 264*f1fbf3c2SXin Li AnnotationsAttribute ainfo = (AnnotationsAttribute) 265*f1fbf3c2SXin Li fi.getAttribute(AnnotationsAttribute.invisibleTag); 266*f1fbf3c2SXin Li AnnotationsAttribute ainfo2 = (AnnotationsAttribute) 267*f1fbf3c2SXin Li fi.getAttribute(AnnotationsAttribute.visibleTag); 268*f1fbf3c2SXin Li return CtClassType.hasAnnotationType(typeName, getDeclaringClass().getClassPool(), 269*f1fbf3c2SXin Li ainfo, ainfo2); 270*f1fbf3c2SXin Li } 271*f1fbf3c2SXin Li 272*f1fbf3c2SXin Li /** 273*f1fbf3c2SXin Li * Returns the annotation if the class has the specified annotation class. 274*f1fbf3c2SXin Li * For example, if an annotation <code>@Author</code> is associated 275*f1fbf3c2SXin Li * with this field, an <code>Author</code> object is returned. 276*f1fbf3c2SXin Li * The member values can be obtained by calling methods on 277*f1fbf3c2SXin Li * the <code>Author</code> object. 278*f1fbf3c2SXin Li * 279*f1fbf3c2SXin Li * @param clz the annotation class. 280*f1fbf3c2SXin Li * @return the annotation if found, otherwise <code>null</code>. 281*f1fbf3c2SXin Li * @since 3.11 282*f1fbf3c2SXin Li */ 283*f1fbf3c2SXin Li @Override getAnnotation(Class<?> clz)284*f1fbf3c2SXin Li public Object getAnnotation(Class<?> clz) throws ClassNotFoundException { 285*f1fbf3c2SXin Li FieldInfo fi = getFieldInfo2(); 286*f1fbf3c2SXin Li AnnotationsAttribute ainfo = (AnnotationsAttribute) 287*f1fbf3c2SXin Li fi.getAttribute(AnnotationsAttribute.invisibleTag); 288*f1fbf3c2SXin Li AnnotationsAttribute ainfo2 = (AnnotationsAttribute) 289*f1fbf3c2SXin Li fi.getAttribute(AnnotationsAttribute.visibleTag); 290*f1fbf3c2SXin Li return CtClassType.getAnnotationType(clz, getDeclaringClass().getClassPool(), 291*f1fbf3c2SXin Li ainfo, ainfo2); 292*f1fbf3c2SXin Li } 293*f1fbf3c2SXin Li 294*f1fbf3c2SXin Li /** 295*f1fbf3c2SXin Li * Returns the annotations associated with this field. 296*f1fbf3c2SXin Li * 297*f1fbf3c2SXin Li * @return an array of annotation-type objects. 298*f1fbf3c2SXin Li * @see #getAvailableAnnotations() 299*f1fbf3c2SXin Li * @since 3.1 300*f1fbf3c2SXin Li */ 301*f1fbf3c2SXin Li @Override getAnnotations()302*f1fbf3c2SXin Li public Object[] getAnnotations() throws ClassNotFoundException { 303*f1fbf3c2SXin Li return getAnnotations(false); 304*f1fbf3c2SXin Li } 305*f1fbf3c2SXin Li 306*f1fbf3c2SXin Li /** 307*f1fbf3c2SXin Li * Returns the annotations associated with this field. 308*f1fbf3c2SXin Li * If any annotations are not on the classpath, they are not included 309*f1fbf3c2SXin Li * in the returned array. 310*f1fbf3c2SXin Li * 311*f1fbf3c2SXin Li * @return an array of annotation-type objects. 312*f1fbf3c2SXin Li * @see #getAnnotations() 313*f1fbf3c2SXin Li * @since 3.3 314*f1fbf3c2SXin Li */ 315*f1fbf3c2SXin Li @Override getAvailableAnnotations()316*f1fbf3c2SXin Li public Object[] getAvailableAnnotations(){ 317*f1fbf3c2SXin Li try { 318*f1fbf3c2SXin Li return getAnnotations(true); 319*f1fbf3c2SXin Li } 320*f1fbf3c2SXin Li catch (ClassNotFoundException e) { 321*f1fbf3c2SXin Li throw new RuntimeException("Unexpected exception", e); 322*f1fbf3c2SXin Li } 323*f1fbf3c2SXin Li } 324*f1fbf3c2SXin Li getAnnotations(boolean ignoreNotFound)325*f1fbf3c2SXin Li private Object[] getAnnotations(boolean ignoreNotFound) throws ClassNotFoundException { 326*f1fbf3c2SXin Li FieldInfo fi = getFieldInfo2(); 327*f1fbf3c2SXin Li AnnotationsAttribute ainfo = (AnnotationsAttribute) 328*f1fbf3c2SXin Li fi.getAttribute(AnnotationsAttribute.invisibleTag); 329*f1fbf3c2SXin Li AnnotationsAttribute ainfo2 = (AnnotationsAttribute) 330*f1fbf3c2SXin Li fi.getAttribute(AnnotationsAttribute.visibleTag); 331*f1fbf3c2SXin Li return CtClassType.toAnnotationType(ignoreNotFound, getDeclaringClass().getClassPool(), 332*f1fbf3c2SXin Li ainfo, ainfo2); 333*f1fbf3c2SXin Li } 334*f1fbf3c2SXin Li 335*f1fbf3c2SXin Li /** 336*f1fbf3c2SXin Li * Returns the character string representing the type of the field. 337*f1fbf3c2SXin Li * The field signature is represented by a character string 338*f1fbf3c2SXin Li * called a field descriptor, which is defined in the JVM specification. 339*f1fbf3c2SXin Li * If two fields have the same type, 340*f1fbf3c2SXin Li * <code>getSignature()</code> returns the same string. 341*f1fbf3c2SXin Li * 342*f1fbf3c2SXin Li * <p>Note that the returned string is not the type signature 343*f1fbf3c2SXin Li * contained in the <code>SignatureAttirbute</code>. It is 344*f1fbf3c2SXin Li * a descriptor. 345*f1fbf3c2SXin Li * 346*f1fbf3c2SXin Li * @see javassist.bytecode.Descriptor 347*f1fbf3c2SXin Li * @see #getGenericSignature() 348*f1fbf3c2SXin Li */ 349*f1fbf3c2SXin Li @Override getSignature()350*f1fbf3c2SXin Li public String getSignature() { 351*f1fbf3c2SXin Li return fieldInfo.getDescriptor(); 352*f1fbf3c2SXin Li } 353*f1fbf3c2SXin Li 354*f1fbf3c2SXin Li /** 355*f1fbf3c2SXin Li * Returns the generic signature of the field. 356*f1fbf3c2SXin Li * It represents a type including type variables. 357*f1fbf3c2SXin Li * 358*f1fbf3c2SXin Li * @see SignatureAttribute#toFieldSignature(String) 359*f1fbf3c2SXin Li * @since 3.17 360*f1fbf3c2SXin Li */ 361*f1fbf3c2SXin Li @Override getGenericSignature()362*f1fbf3c2SXin Li public String getGenericSignature() { 363*f1fbf3c2SXin Li SignatureAttribute sa 364*f1fbf3c2SXin Li = (SignatureAttribute)fieldInfo.getAttribute(SignatureAttribute.tag); 365*f1fbf3c2SXin Li return sa == null ? null : sa.getSignature(); 366*f1fbf3c2SXin Li } 367*f1fbf3c2SXin Li 368*f1fbf3c2SXin Li /** 369*f1fbf3c2SXin Li * Set the generic signature of the field. 370*f1fbf3c2SXin Li * It represents a type including type variables. 371*f1fbf3c2SXin Li * See {@link javassist.CtClass#setGenericSignature(String)} 372*f1fbf3c2SXin Li * for a code sample. 373*f1fbf3c2SXin Li * 374*f1fbf3c2SXin Li * @param sig a new generic signature. 375*f1fbf3c2SXin Li * @see javassist.bytecode.SignatureAttribute.ObjectType#encode() 376*f1fbf3c2SXin Li * @since 3.17 377*f1fbf3c2SXin Li */ 378*f1fbf3c2SXin Li @Override setGenericSignature(String sig)379*f1fbf3c2SXin Li public void setGenericSignature(String sig) { 380*f1fbf3c2SXin Li declaringClass.checkModify(); 381*f1fbf3c2SXin Li fieldInfo.addAttribute(new SignatureAttribute(fieldInfo.getConstPool(), sig)); 382*f1fbf3c2SXin Li } 383*f1fbf3c2SXin Li 384*f1fbf3c2SXin Li /** 385*f1fbf3c2SXin Li * Returns the type of the field. 386*f1fbf3c2SXin Li */ getType()387*f1fbf3c2SXin Li public CtClass getType() throws NotFoundException { 388*f1fbf3c2SXin Li return Descriptor.toCtClass(fieldInfo.getDescriptor(), 389*f1fbf3c2SXin Li declaringClass.getClassPool()); 390*f1fbf3c2SXin Li } 391*f1fbf3c2SXin Li 392*f1fbf3c2SXin Li /** 393*f1fbf3c2SXin Li * Sets the type of the field. 394*f1fbf3c2SXin Li * 395*f1fbf3c2SXin Li * <p>This method does not automatically update method bodies that access 396*f1fbf3c2SXin Li * this field. They have to be explicitly updated. For example, 397*f1fbf3c2SXin Li * if some method contains an expression {@code t.value} and the type 398*f1fbf3c2SXin Li * of the variable {@code t} is changed by {@link #setType(CtClass)} 399*f1fbf3c2SXin Li * from {@code int} to {@code double}, then {@code t.value} has to be modified 400*f1fbf3c2SXin Li * as well since the bytecode of {@code t.value} contains the type information. 401*f1fbf3c2SXin Li * </p> 402*f1fbf3c2SXin Li * 403*f1fbf3c2SXin Li * @see CodeConverter 404*f1fbf3c2SXin Li * @see javassist.expr.ExprEditor 405*f1fbf3c2SXin Li */ setType(CtClass clazz)406*f1fbf3c2SXin Li public void setType(CtClass clazz) { 407*f1fbf3c2SXin Li declaringClass.checkModify(); 408*f1fbf3c2SXin Li fieldInfo.setDescriptor(Descriptor.of(clazz)); 409*f1fbf3c2SXin Li } 410*f1fbf3c2SXin Li 411*f1fbf3c2SXin Li /** 412*f1fbf3c2SXin Li * Returns the value of this field if it is a constant field. 413*f1fbf3c2SXin Li * This method works only if the field type is a primitive type 414*f1fbf3c2SXin Li * or <code>String</code> type. Otherwise, it returns <code>null</code>. 415*f1fbf3c2SXin Li * A constant field is <code>static</code> and <code>final</code>. 416*f1fbf3c2SXin Li * 417*f1fbf3c2SXin Li * @return a <code>Integer</code>, <code>Long</code>, <code>Float</code>, 418*f1fbf3c2SXin Li * <code>Double</code>, <code>Boolean</code>, 419*f1fbf3c2SXin Li * or <code>String</code> object 420*f1fbf3c2SXin Li * representing the constant value. 421*f1fbf3c2SXin Li * <code>null</code> if it is not a constant field 422*f1fbf3c2SXin Li * or if the field type is not a primitive type 423*f1fbf3c2SXin Li * or <code>String</code>. 424*f1fbf3c2SXin Li */ getConstantValue()425*f1fbf3c2SXin Li public Object getConstantValue() { 426*f1fbf3c2SXin Li // When this method is modified, 427*f1fbf3c2SXin Li // see also getConstantFieldValue() in TypeChecker. 428*f1fbf3c2SXin Li 429*f1fbf3c2SXin Li int index = fieldInfo.getConstantValue(); 430*f1fbf3c2SXin Li if (index == 0) 431*f1fbf3c2SXin Li return null; 432*f1fbf3c2SXin Li 433*f1fbf3c2SXin Li ConstPool cp = fieldInfo.getConstPool(); 434*f1fbf3c2SXin Li switch (cp.getTag(index)) { 435*f1fbf3c2SXin Li case ConstPool.CONST_Long : 436*f1fbf3c2SXin Li return Long.valueOf(cp.getLongInfo(index)); 437*f1fbf3c2SXin Li case ConstPool.CONST_Float : 438*f1fbf3c2SXin Li return Float.valueOf(cp.getFloatInfo(index)); 439*f1fbf3c2SXin Li case ConstPool.CONST_Double : 440*f1fbf3c2SXin Li return Double.valueOf(cp.getDoubleInfo(index)); 441*f1fbf3c2SXin Li case ConstPool.CONST_Integer : 442*f1fbf3c2SXin Li int value = cp.getIntegerInfo(index); 443*f1fbf3c2SXin Li // "Z" means boolean type. 444*f1fbf3c2SXin Li if ("Z".equals(fieldInfo.getDescriptor())) 445*f1fbf3c2SXin Li return Boolean.valueOf(value != 0); 446*f1fbf3c2SXin Li return Integer.valueOf(value); 447*f1fbf3c2SXin Li case ConstPool.CONST_String : 448*f1fbf3c2SXin Li return cp.getStringInfo(index); 449*f1fbf3c2SXin Li default : 450*f1fbf3c2SXin Li throw new RuntimeException("bad tag: " + cp.getTag(index) 451*f1fbf3c2SXin Li + " at " + index); 452*f1fbf3c2SXin Li } 453*f1fbf3c2SXin Li } 454*f1fbf3c2SXin Li 455*f1fbf3c2SXin Li /** 456*f1fbf3c2SXin Li * Obtains an attribute with the given name. 457*f1fbf3c2SXin Li * If that attribute is not found in the class file, this 458*f1fbf3c2SXin Li * method returns null. 459*f1fbf3c2SXin Li * 460*f1fbf3c2SXin Li * <p>Note that an attribute is a data block specified by 461*f1fbf3c2SXin Li * the class file format. 462*f1fbf3c2SXin Li * See {@link javassist.bytecode.AttributeInfo}. 463*f1fbf3c2SXin Li * 464*f1fbf3c2SXin Li * @param name attribute name 465*f1fbf3c2SXin Li */ 466*f1fbf3c2SXin Li @Override getAttribute(String name)467*f1fbf3c2SXin Li public byte[] getAttribute(String name) { 468*f1fbf3c2SXin Li AttributeInfo ai = fieldInfo.getAttribute(name); 469*f1fbf3c2SXin Li if (ai == null) 470*f1fbf3c2SXin Li return null; 471*f1fbf3c2SXin Li return ai.get(); 472*f1fbf3c2SXin Li } 473*f1fbf3c2SXin Li 474*f1fbf3c2SXin Li /** 475*f1fbf3c2SXin Li * Adds an attribute. The attribute is saved in the class file. 476*f1fbf3c2SXin Li * 477*f1fbf3c2SXin Li * <p>Note that an attribute is a data block specified by 478*f1fbf3c2SXin Li * the class file format. 479*f1fbf3c2SXin Li * See {@link javassist.bytecode.AttributeInfo}. 480*f1fbf3c2SXin Li * 481*f1fbf3c2SXin Li * @param name attribute name 482*f1fbf3c2SXin Li * @param data attribute value 483*f1fbf3c2SXin Li */ 484*f1fbf3c2SXin Li @Override setAttribute(String name, byte[] data)485*f1fbf3c2SXin Li public void setAttribute(String name, byte[] data) { 486*f1fbf3c2SXin Li declaringClass.checkModify(); 487*f1fbf3c2SXin Li fieldInfo.addAttribute(new AttributeInfo(fieldInfo.getConstPool(), 488*f1fbf3c2SXin Li name, data)); 489*f1fbf3c2SXin Li } 490*f1fbf3c2SXin Li 491*f1fbf3c2SXin Li // inner classes 492*f1fbf3c2SXin Li 493*f1fbf3c2SXin Li /** 494*f1fbf3c2SXin Li * Instances of this class specify how to initialize a field. 495*f1fbf3c2SXin Li * <code>Initializer</code> is passed to 496*f1fbf3c2SXin Li * <code>CtClass.addField()</code> with a <code>CtField</code>. 497*f1fbf3c2SXin Li * 498*f1fbf3c2SXin Li * <p>This class cannot be instantiated with the <code>new</code> operator. 499*f1fbf3c2SXin Li * Factory methods such as <code>byParameter()</code> and 500*f1fbf3c2SXin Li * <code>byNew</code> 501*f1fbf3c2SXin Li * must be used for the instantiation. They create a new instance with 502*f1fbf3c2SXin Li * the given parameters and return it. 503*f1fbf3c2SXin Li * 504*f1fbf3c2SXin Li * @see CtClass#addField(CtField,CtField.Initializer) 505*f1fbf3c2SXin Li */ 506*f1fbf3c2SXin Li public static abstract class Initializer { 507*f1fbf3c2SXin Li /** 508*f1fbf3c2SXin Li * Makes an initializer that assigns a constant integer value. 509*f1fbf3c2SXin Li * The field must be integer, short, char, or byte type. 510*f1fbf3c2SXin Li */ constant(int i)511*f1fbf3c2SXin Li public static Initializer constant(int i) { 512*f1fbf3c2SXin Li return new IntInitializer(i); 513*f1fbf3c2SXin Li } 514*f1fbf3c2SXin Li 515*f1fbf3c2SXin Li /** 516*f1fbf3c2SXin Li * Makes an initializer that assigns a constant boolean value. 517*f1fbf3c2SXin Li * The field must be boolean type. 518*f1fbf3c2SXin Li */ constant(boolean b)519*f1fbf3c2SXin Li public static Initializer constant(boolean b) { 520*f1fbf3c2SXin Li return new IntInitializer(b ? 1 : 0); 521*f1fbf3c2SXin Li } 522*f1fbf3c2SXin Li 523*f1fbf3c2SXin Li /** 524*f1fbf3c2SXin Li * Makes an initializer that assigns a constant long value. 525*f1fbf3c2SXin Li * The field must be long type. 526*f1fbf3c2SXin Li */ constant(long l)527*f1fbf3c2SXin Li public static Initializer constant(long l) { 528*f1fbf3c2SXin Li return new LongInitializer(l); 529*f1fbf3c2SXin Li } 530*f1fbf3c2SXin Li 531*f1fbf3c2SXin Li /** 532*f1fbf3c2SXin Li * Makes an initializer that assigns a constant float value. 533*f1fbf3c2SXin Li * The field must be float type. 534*f1fbf3c2SXin Li */ constant(float l)535*f1fbf3c2SXin Li public static Initializer constant(float l) { 536*f1fbf3c2SXin Li return new FloatInitializer(l); 537*f1fbf3c2SXin Li } 538*f1fbf3c2SXin Li 539*f1fbf3c2SXin Li /** 540*f1fbf3c2SXin Li * Makes an initializer that assigns a constant double value. 541*f1fbf3c2SXin Li * The field must be double type. 542*f1fbf3c2SXin Li */ constant(double d)543*f1fbf3c2SXin Li public static Initializer constant(double d) { 544*f1fbf3c2SXin Li return new DoubleInitializer(d); 545*f1fbf3c2SXin Li } 546*f1fbf3c2SXin Li 547*f1fbf3c2SXin Li /** 548*f1fbf3c2SXin Li * Makes an initializer that assigns a constant string value. 549*f1fbf3c2SXin Li * The field must be <code>java.lang.String</code> type. 550*f1fbf3c2SXin Li */ constant(String s)551*f1fbf3c2SXin Li public static Initializer constant(String s) { 552*f1fbf3c2SXin Li return new StringInitializer(s); 553*f1fbf3c2SXin Li } 554*f1fbf3c2SXin Li 555*f1fbf3c2SXin Li /** 556*f1fbf3c2SXin Li * Makes an initializer using a constructor parameter. 557*f1fbf3c2SXin Li * 558*f1fbf3c2SXin Li * <p>The initial value is the 559*f1fbf3c2SXin Li * N-th parameter given to the constructor of the object including 560*f1fbf3c2SXin Li * the field. If the constructor takes less than N parameters, 561*f1fbf3c2SXin Li * the field is not initialized. 562*f1fbf3c2SXin Li * If the field is static, it is never initialized. 563*f1fbf3c2SXin Li * 564*f1fbf3c2SXin Li * @param nth the n-th (>= 0) parameter is used as 565*f1fbf3c2SXin Li * the initial value. 566*f1fbf3c2SXin Li * If nth is 0, then the first parameter is 567*f1fbf3c2SXin Li * used. 568*f1fbf3c2SXin Li */ byParameter(int nth)569*f1fbf3c2SXin Li public static Initializer byParameter(int nth) { 570*f1fbf3c2SXin Li ParamInitializer i = new ParamInitializer(); 571*f1fbf3c2SXin Li i.nthParam = nth; 572*f1fbf3c2SXin Li return i; 573*f1fbf3c2SXin Li } 574*f1fbf3c2SXin Li 575*f1fbf3c2SXin Li /** 576*f1fbf3c2SXin Li * Makes an initializer creating a new object. 577*f1fbf3c2SXin Li * 578*f1fbf3c2SXin Li * <p>This initializer creates a new object and uses it as the initial 579*f1fbf3c2SXin Li * value of the field. The constructor of the created object receives 580*f1fbf3c2SXin Li * the parameter: 581*f1fbf3c2SXin Li * 582*f1fbf3c2SXin Li * <p><code>Object obj</code> - the object including the field. 583*f1fbf3c2SXin Li * 584*f1fbf3c2SXin Li * <p>If the initialized field is static, then the constructor does 585*f1fbf3c2SXin Li * not receive any parameters. 586*f1fbf3c2SXin Li * 587*f1fbf3c2SXin Li * @param objectType the class instantiated for the initial value. 588*f1fbf3c2SXin Li */ byNew(CtClass objectType)589*f1fbf3c2SXin Li public static Initializer byNew(CtClass objectType) { 590*f1fbf3c2SXin Li NewInitializer i = new NewInitializer(); 591*f1fbf3c2SXin Li i.objectType = objectType; 592*f1fbf3c2SXin Li i.stringParams = null; 593*f1fbf3c2SXin Li i.withConstructorParams = false; 594*f1fbf3c2SXin Li return i; 595*f1fbf3c2SXin Li } 596*f1fbf3c2SXin Li 597*f1fbf3c2SXin Li /** 598*f1fbf3c2SXin Li * Makes an initializer creating a new object. 599*f1fbf3c2SXin Li * 600*f1fbf3c2SXin Li * <p>This initializer creates a new object and uses it as the initial 601*f1fbf3c2SXin Li * value of the field. The constructor of the created object receives 602*f1fbf3c2SXin Li * the parameters: 603*f1fbf3c2SXin Li * 604*f1fbf3c2SXin Li * <p><code>Object obj</code> - the object including the field.<br> 605*f1fbf3c2SXin Li * <code>String[] strs</code> - the character strings specified 606*f1fbf3c2SXin Li * by <code>stringParams</code><br> 607*f1fbf3c2SXin Li * 608*f1fbf3c2SXin Li * <p>If the initialized field is static, then the constructor 609*f1fbf3c2SXin Li * receives only <code>strs</code>. 610*f1fbf3c2SXin Li * 611*f1fbf3c2SXin Li * @param objectType the class instantiated for the initial value. 612*f1fbf3c2SXin Li * @param stringParams the array of strings passed to the 613*f1fbf3c2SXin Li * constructor. 614*f1fbf3c2SXin Li */ byNew(CtClass objectType, String[] stringParams)615*f1fbf3c2SXin Li public static Initializer byNew(CtClass objectType, 616*f1fbf3c2SXin Li String[] stringParams) { 617*f1fbf3c2SXin Li NewInitializer i = new NewInitializer(); 618*f1fbf3c2SXin Li i.objectType = objectType; 619*f1fbf3c2SXin Li i.stringParams = stringParams; 620*f1fbf3c2SXin Li i.withConstructorParams = false; 621*f1fbf3c2SXin Li return i; 622*f1fbf3c2SXin Li } 623*f1fbf3c2SXin Li 624*f1fbf3c2SXin Li /** 625*f1fbf3c2SXin Li * Makes an initializer creating a new object. 626*f1fbf3c2SXin Li * 627*f1fbf3c2SXin Li * <p>This initializer creates a new object and uses it as the initial 628*f1fbf3c2SXin Li * value of the field. The constructor of the created object receives 629*f1fbf3c2SXin Li * the parameters: 630*f1fbf3c2SXin Li * 631*f1fbf3c2SXin Li * <p><code>Object obj</code> - the object including the field.<br> 632*f1fbf3c2SXin Li * <code>Object[] args</code> - the parameters passed to the 633*f1fbf3c2SXin Li * constructor of the object including the 634*f1fbf3c2SXin Li * filed. 635*f1fbf3c2SXin Li * 636*f1fbf3c2SXin Li * <p>If the initialized field is static, then the constructor does 637*f1fbf3c2SXin Li * not receive any parameters. 638*f1fbf3c2SXin Li * 639*f1fbf3c2SXin Li * @param objectType the class instantiated for the initial value. 640*f1fbf3c2SXin Li * 641*f1fbf3c2SXin Li * @see javassist.CtField.Initializer#byNewArray(CtClass,int) 642*f1fbf3c2SXin Li * @see javassist.CtField.Initializer#byNewArray(CtClass,int[]) 643*f1fbf3c2SXin Li */ byNewWithParams(CtClass objectType)644*f1fbf3c2SXin Li public static Initializer byNewWithParams(CtClass objectType) { 645*f1fbf3c2SXin Li NewInitializer i = new NewInitializer(); 646*f1fbf3c2SXin Li i.objectType = objectType; 647*f1fbf3c2SXin Li i.stringParams = null; 648*f1fbf3c2SXin Li i.withConstructorParams = true; 649*f1fbf3c2SXin Li return i; 650*f1fbf3c2SXin Li } 651*f1fbf3c2SXin Li 652*f1fbf3c2SXin Li /** 653*f1fbf3c2SXin Li * Makes an initializer creating a new object. 654*f1fbf3c2SXin Li * 655*f1fbf3c2SXin Li * <p>This initializer creates a new object and uses it as the initial 656*f1fbf3c2SXin Li * value of the field. The constructor of the created object receives 657*f1fbf3c2SXin Li * the parameters: 658*f1fbf3c2SXin Li * 659*f1fbf3c2SXin Li * <p><code>Object obj</code> - the object including the field.<br> 660*f1fbf3c2SXin Li * <code>String[] strs</code> - the character strings specified 661*f1fbf3c2SXin Li * by <code>stringParams</code><br> 662*f1fbf3c2SXin Li * <code>Object[] args</code> - the parameters passed to the 663*f1fbf3c2SXin Li * constructor of the object including the 664*f1fbf3c2SXin Li * filed. 665*f1fbf3c2SXin Li * 666*f1fbf3c2SXin Li * <p>If the initialized field is static, then the constructor receives 667*f1fbf3c2SXin Li * only <code>strs</code>. 668*f1fbf3c2SXin Li * 669*f1fbf3c2SXin Li * @param objectType the class instantiated for the initial value. 670*f1fbf3c2SXin Li * @param stringParams the array of strings passed to the 671*f1fbf3c2SXin Li * constructor. 672*f1fbf3c2SXin Li */ byNewWithParams(CtClass objectType, String[] stringParams)673*f1fbf3c2SXin Li public static Initializer byNewWithParams(CtClass objectType, 674*f1fbf3c2SXin Li String[] stringParams) { 675*f1fbf3c2SXin Li NewInitializer i = new NewInitializer(); 676*f1fbf3c2SXin Li i.objectType = objectType; 677*f1fbf3c2SXin Li i.stringParams = stringParams; 678*f1fbf3c2SXin Li i.withConstructorParams = true; 679*f1fbf3c2SXin Li return i; 680*f1fbf3c2SXin Li } 681*f1fbf3c2SXin Li 682*f1fbf3c2SXin Li /** 683*f1fbf3c2SXin Li * Makes an initializer calling a static method. 684*f1fbf3c2SXin Li * 685*f1fbf3c2SXin Li * <p>This initializer calls a static method and uses the returned 686*f1fbf3c2SXin Li * value as the initial value of the field. 687*f1fbf3c2SXin Li * The called method receives the parameters: 688*f1fbf3c2SXin Li * 689*f1fbf3c2SXin Li * <p><code>Object obj</code> - the object including the field. 690*f1fbf3c2SXin Li * 691*f1fbf3c2SXin Li * <p>If the initialized field is static, then the method does 692*f1fbf3c2SXin Li * not receive any parameters. 693*f1fbf3c2SXin Li * 694*f1fbf3c2SXin Li * <p>The type of the returned value must be the same as the field 695*f1fbf3c2SXin Li * type. 696*f1fbf3c2SXin Li * 697*f1fbf3c2SXin Li * @param methodClass the class that the static method is 698*f1fbf3c2SXin Li * declared in. 699*f1fbf3c2SXin Li * @param methodName the name of the satic method. 700*f1fbf3c2SXin Li */ byCall(CtClass methodClass, String methodName)701*f1fbf3c2SXin Li public static Initializer byCall(CtClass methodClass, 702*f1fbf3c2SXin Li String methodName) { 703*f1fbf3c2SXin Li MethodInitializer i = new MethodInitializer(); 704*f1fbf3c2SXin Li i.objectType = methodClass; 705*f1fbf3c2SXin Li i.methodName = methodName; 706*f1fbf3c2SXin Li i.stringParams = null; 707*f1fbf3c2SXin Li i.withConstructorParams = false; 708*f1fbf3c2SXin Li return i; 709*f1fbf3c2SXin Li } 710*f1fbf3c2SXin Li 711*f1fbf3c2SXin Li /** 712*f1fbf3c2SXin Li * Makes an initializer calling a static method. 713*f1fbf3c2SXin Li * 714*f1fbf3c2SXin Li * <p>This initializer calls a static method and uses the returned 715*f1fbf3c2SXin Li * value as the initial value of the field. The called method 716*f1fbf3c2SXin Li * receives the parameters: 717*f1fbf3c2SXin Li * 718*f1fbf3c2SXin Li * <p><code>Object obj</code> - the object including the field.<br> 719*f1fbf3c2SXin Li * <code>String[] strs</code> - the character strings specified 720*f1fbf3c2SXin Li * by <code>stringParams</code><br> 721*f1fbf3c2SXin Li * 722*f1fbf3c2SXin Li * <p>If the initialized field is static, then the method 723*f1fbf3c2SXin Li * receive only <code>strs</code>. 724*f1fbf3c2SXin Li * 725*f1fbf3c2SXin Li * <p>The type of the returned value must be the same as the field 726*f1fbf3c2SXin Li * type. 727*f1fbf3c2SXin Li * 728*f1fbf3c2SXin Li * @param methodClass the class that the static method is 729*f1fbf3c2SXin Li * declared in. 730*f1fbf3c2SXin Li * @param methodName the name of the satic method. 731*f1fbf3c2SXin Li * @param stringParams the array of strings passed to the 732*f1fbf3c2SXin Li * static method. 733*f1fbf3c2SXin Li */ byCall(CtClass methodClass, String methodName, String[] stringParams)734*f1fbf3c2SXin Li public static Initializer byCall(CtClass methodClass, 735*f1fbf3c2SXin Li String methodName, 736*f1fbf3c2SXin Li String[] stringParams) { 737*f1fbf3c2SXin Li MethodInitializer i = new MethodInitializer(); 738*f1fbf3c2SXin Li i.objectType = methodClass; 739*f1fbf3c2SXin Li i.methodName = methodName; 740*f1fbf3c2SXin Li i.stringParams = stringParams; 741*f1fbf3c2SXin Li i.withConstructorParams = false; 742*f1fbf3c2SXin Li return i; 743*f1fbf3c2SXin Li } 744*f1fbf3c2SXin Li 745*f1fbf3c2SXin Li /** 746*f1fbf3c2SXin Li * Makes an initializer calling a static method. 747*f1fbf3c2SXin Li * 748*f1fbf3c2SXin Li * <p>This initializer calls a static method and uses the returned 749*f1fbf3c2SXin Li * value as the initial value of the field. The called method 750*f1fbf3c2SXin Li * receives the parameters: 751*f1fbf3c2SXin Li * 752*f1fbf3c2SXin Li * <p><code>Object obj</code> - the object including the field.<br> 753*f1fbf3c2SXin Li * <code>Object[] args</code> - the parameters passed to the 754*f1fbf3c2SXin Li * constructor of the object including the 755*f1fbf3c2SXin Li * filed. 756*f1fbf3c2SXin Li * 757*f1fbf3c2SXin Li * <p>If the initialized field is static, then the method does 758*f1fbf3c2SXin Li * not receive any parameters. 759*f1fbf3c2SXin Li * 760*f1fbf3c2SXin Li * <p>The type of the returned value must be the same as the field 761*f1fbf3c2SXin Li * type. 762*f1fbf3c2SXin Li * 763*f1fbf3c2SXin Li * @param methodClass the class that the static method is 764*f1fbf3c2SXin Li * declared in. 765*f1fbf3c2SXin Li * @param methodName the name of the satic method. 766*f1fbf3c2SXin Li */ byCallWithParams(CtClass methodClass, String methodName)767*f1fbf3c2SXin Li public static Initializer byCallWithParams(CtClass methodClass, 768*f1fbf3c2SXin Li String methodName) { 769*f1fbf3c2SXin Li MethodInitializer i = new MethodInitializer(); 770*f1fbf3c2SXin Li i.objectType = methodClass; 771*f1fbf3c2SXin Li i.methodName = methodName; 772*f1fbf3c2SXin Li i.stringParams = null; 773*f1fbf3c2SXin Li i.withConstructorParams = true; 774*f1fbf3c2SXin Li return i; 775*f1fbf3c2SXin Li } 776*f1fbf3c2SXin Li 777*f1fbf3c2SXin Li /** 778*f1fbf3c2SXin Li * Makes an initializer calling a static method. 779*f1fbf3c2SXin Li * 780*f1fbf3c2SXin Li * <p>This initializer calls a static method and uses the returned 781*f1fbf3c2SXin Li * value as the initial value of the field. The called method 782*f1fbf3c2SXin Li * receives the parameters: 783*f1fbf3c2SXin Li * 784*f1fbf3c2SXin Li * <p><code>Object obj</code> - the object including the field.<br> 785*f1fbf3c2SXin Li * <code>String[] strs</code> - the character strings specified 786*f1fbf3c2SXin Li * by <code>stringParams</code><br> 787*f1fbf3c2SXin Li * <code>Object[] args</code> - the parameters passed to the 788*f1fbf3c2SXin Li * constructor of the object including the 789*f1fbf3c2SXin Li * filed. 790*f1fbf3c2SXin Li * 791*f1fbf3c2SXin Li * <p>If the initialized field is static, then the method 792*f1fbf3c2SXin Li * receive only <code>strs</code>. 793*f1fbf3c2SXin Li * 794*f1fbf3c2SXin Li * <p>The type of the returned value must be the same as the field 795*f1fbf3c2SXin Li * type. 796*f1fbf3c2SXin Li * 797*f1fbf3c2SXin Li * @param methodClass the class that the static method is 798*f1fbf3c2SXin Li * declared in. 799*f1fbf3c2SXin Li * @param methodName the name of the satic method. 800*f1fbf3c2SXin Li * @param stringParams the array of strings passed to the 801*f1fbf3c2SXin Li * static method. 802*f1fbf3c2SXin Li */ byCallWithParams(CtClass methodClass, String methodName, String[] stringParams)803*f1fbf3c2SXin Li public static Initializer byCallWithParams(CtClass methodClass, 804*f1fbf3c2SXin Li String methodName, String[] stringParams) { 805*f1fbf3c2SXin Li MethodInitializer i = new MethodInitializer(); 806*f1fbf3c2SXin Li i.objectType = methodClass; 807*f1fbf3c2SXin Li i.methodName = methodName; 808*f1fbf3c2SXin Li i.stringParams = stringParams; 809*f1fbf3c2SXin Li i.withConstructorParams = true; 810*f1fbf3c2SXin Li return i; 811*f1fbf3c2SXin Li } 812*f1fbf3c2SXin Li 813*f1fbf3c2SXin Li /** 814*f1fbf3c2SXin Li * Makes an initializer creating a new array. 815*f1fbf3c2SXin Li * 816*f1fbf3c2SXin Li * @param type the type of the array. 817*f1fbf3c2SXin Li * @param size the size of the array. 818*f1fbf3c2SXin Li * @throws NotFoundException if the type of the array components 819*f1fbf3c2SXin Li * is not found. 820*f1fbf3c2SXin Li */ byNewArray(CtClass type, int size)821*f1fbf3c2SXin Li public static Initializer byNewArray(CtClass type, int size) 822*f1fbf3c2SXin Li throws NotFoundException 823*f1fbf3c2SXin Li { 824*f1fbf3c2SXin Li return new ArrayInitializer(type.getComponentType(), size); 825*f1fbf3c2SXin Li } 826*f1fbf3c2SXin Li 827*f1fbf3c2SXin Li /** 828*f1fbf3c2SXin Li * Makes an initializer creating a new multi-dimensional array. 829*f1fbf3c2SXin Li * 830*f1fbf3c2SXin Li * @param type the type of the array. 831*f1fbf3c2SXin Li * @param sizes an <code>int</code> array of the size in every 832*f1fbf3c2SXin Li * dimension. 833*f1fbf3c2SXin Li * The first element is the size in the first 834*f1fbf3c2SXin Li * dimension. The second is in the second, etc. 835*f1fbf3c2SXin Li */ byNewArray(CtClass type, int[] sizes)836*f1fbf3c2SXin Li public static Initializer byNewArray(CtClass type, int[] sizes) { 837*f1fbf3c2SXin Li return new MultiArrayInitializer(type, sizes); 838*f1fbf3c2SXin Li } 839*f1fbf3c2SXin Li 840*f1fbf3c2SXin Li /** 841*f1fbf3c2SXin Li * Makes an initializer. 842*f1fbf3c2SXin Li * 843*f1fbf3c2SXin Li * @param source initializer expression. 844*f1fbf3c2SXin Li */ byExpr(String source)845*f1fbf3c2SXin Li public static Initializer byExpr(String source) { 846*f1fbf3c2SXin Li return new CodeInitializer(source); 847*f1fbf3c2SXin Li } 848*f1fbf3c2SXin Li byExpr(ASTree source)849*f1fbf3c2SXin Li static Initializer byExpr(ASTree source) { 850*f1fbf3c2SXin Li return new PtreeInitializer(source); 851*f1fbf3c2SXin Li } 852*f1fbf3c2SXin Li 853*f1fbf3c2SXin Li // Check whether this initializer is valid for the field type. 854*f1fbf3c2SXin Li // If it is invaild, this method throws an exception. check(String desc)855*f1fbf3c2SXin Li void check(String desc) throws CannotCompileException {} 856*f1fbf3c2SXin Li 857*f1fbf3c2SXin Li // produce codes for initialization compile(CtClass type, String name, Bytecode code, CtClass[] parameters, Javac drv)858*f1fbf3c2SXin Li abstract int compile(CtClass type, String name, Bytecode code, 859*f1fbf3c2SXin Li CtClass[] parameters, Javac drv) 860*f1fbf3c2SXin Li throws CannotCompileException; 861*f1fbf3c2SXin Li 862*f1fbf3c2SXin Li // produce codes for initialization compileIfStatic(CtClass type, String name, Bytecode code, Javac drv)863*f1fbf3c2SXin Li abstract int compileIfStatic(CtClass type, String name, 864*f1fbf3c2SXin Li Bytecode code, Javac drv) throws CannotCompileException; 865*f1fbf3c2SXin Li 866*f1fbf3c2SXin Li // returns the index of CONSTANT_Integer_info etc 867*f1fbf3c2SXin Li // if the value is constant. Otherwise, 0. getConstantValue(ConstPool cp, CtClass type)868*f1fbf3c2SXin Li int getConstantValue(ConstPool cp, CtClass type) { return 0; } 869*f1fbf3c2SXin Li } 870*f1fbf3c2SXin Li 871*f1fbf3c2SXin Li static abstract class CodeInitializer0 extends Initializer { compileExpr(Javac drv)872*f1fbf3c2SXin Li abstract void compileExpr(Javac drv) throws CompileError; 873*f1fbf3c2SXin Li 874*f1fbf3c2SXin Li @Override compile(CtClass type, String name, Bytecode code, CtClass[] parameters, Javac drv)875*f1fbf3c2SXin Li int compile(CtClass type, String name, Bytecode code, 876*f1fbf3c2SXin Li CtClass[] parameters, Javac drv) 877*f1fbf3c2SXin Li throws CannotCompileException 878*f1fbf3c2SXin Li { 879*f1fbf3c2SXin Li try { 880*f1fbf3c2SXin Li code.addAload(0); 881*f1fbf3c2SXin Li compileExpr(drv); 882*f1fbf3c2SXin Li code.addPutfield(Bytecode.THIS, name, Descriptor.of(type)); 883*f1fbf3c2SXin Li return code.getMaxStack(); 884*f1fbf3c2SXin Li } 885*f1fbf3c2SXin Li catch (CompileError e) { 886*f1fbf3c2SXin Li throw new CannotCompileException(e); 887*f1fbf3c2SXin Li } 888*f1fbf3c2SXin Li } 889*f1fbf3c2SXin Li 890*f1fbf3c2SXin Li @Override compileIfStatic(CtClass type, String name, Bytecode code, Javac drv)891*f1fbf3c2SXin Li int compileIfStatic(CtClass type, String name, Bytecode code, 892*f1fbf3c2SXin Li Javac drv) throws CannotCompileException 893*f1fbf3c2SXin Li { 894*f1fbf3c2SXin Li try { 895*f1fbf3c2SXin Li compileExpr(drv); 896*f1fbf3c2SXin Li code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type)); 897*f1fbf3c2SXin Li return code.getMaxStack(); 898*f1fbf3c2SXin Li } 899*f1fbf3c2SXin Li catch (CompileError e) { 900*f1fbf3c2SXin Li throw new CannotCompileException(e); 901*f1fbf3c2SXin Li } 902*f1fbf3c2SXin Li } 903*f1fbf3c2SXin Li getConstantValue2(ConstPool cp, CtClass type, ASTree tree)904*f1fbf3c2SXin Li int getConstantValue2(ConstPool cp, CtClass type, ASTree tree) { 905*f1fbf3c2SXin Li if (type.isPrimitive()) { 906*f1fbf3c2SXin Li if (tree instanceof IntConst) { 907*f1fbf3c2SXin Li long value = ((IntConst)tree).get(); 908*f1fbf3c2SXin Li if (type == CtClass.doubleType) 909*f1fbf3c2SXin Li return cp.addDoubleInfo(value); 910*f1fbf3c2SXin Li else if (type == CtClass.floatType) 911*f1fbf3c2SXin Li return cp.addFloatInfo(value); 912*f1fbf3c2SXin Li else if (type == CtClass.longType) 913*f1fbf3c2SXin Li return cp.addLongInfo(value); 914*f1fbf3c2SXin Li else if (type != CtClass.voidType) 915*f1fbf3c2SXin Li return cp.addIntegerInfo((int)value); 916*f1fbf3c2SXin Li } 917*f1fbf3c2SXin Li else if (tree instanceof DoubleConst) { 918*f1fbf3c2SXin Li double value = ((DoubleConst)tree).get(); 919*f1fbf3c2SXin Li if (type == CtClass.floatType) 920*f1fbf3c2SXin Li return cp.addFloatInfo((float)value); 921*f1fbf3c2SXin Li else if (type == CtClass.doubleType) 922*f1fbf3c2SXin Li return cp.addDoubleInfo(value); 923*f1fbf3c2SXin Li } 924*f1fbf3c2SXin Li } 925*f1fbf3c2SXin Li else if (tree instanceof StringL 926*f1fbf3c2SXin Li && type.getName().equals(javaLangString)) 927*f1fbf3c2SXin Li return cp.addStringInfo(((StringL)tree).get()); 928*f1fbf3c2SXin Li 929*f1fbf3c2SXin Li return 0; 930*f1fbf3c2SXin Li } 931*f1fbf3c2SXin Li } 932*f1fbf3c2SXin Li 933*f1fbf3c2SXin Li static class CodeInitializer extends CodeInitializer0 { 934*f1fbf3c2SXin Li private String expression; 935*f1fbf3c2SXin Li CodeInitializer(String expr)936*f1fbf3c2SXin Li CodeInitializer(String expr) { expression = expr; } 937*f1fbf3c2SXin Li 938*f1fbf3c2SXin Li @Override compileExpr(Javac drv)939*f1fbf3c2SXin Li void compileExpr(Javac drv) throws CompileError { 940*f1fbf3c2SXin Li drv.compileExpr(expression); 941*f1fbf3c2SXin Li } 942*f1fbf3c2SXin Li 943*f1fbf3c2SXin Li @Override getConstantValue(ConstPool cp, CtClass type)944*f1fbf3c2SXin Li int getConstantValue(ConstPool cp, CtClass type) { 945*f1fbf3c2SXin Li try { 946*f1fbf3c2SXin Li ASTree t = Javac.parseExpr(expression, new SymbolTable()); 947*f1fbf3c2SXin Li return getConstantValue2(cp, type, t); 948*f1fbf3c2SXin Li } 949*f1fbf3c2SXin Li catch (CompileError e) { 950*f1fbf3c2SXin Li return 0; 951*f1fbf3c2SXin Li } 952*f1fbf3c2SXin Li } 953*f1fbf3c2SXin Li } 954*f1fbf3c2SXin Li 955*f1fbf3c2SXin Li static class PtreeInitializer extends CodeInitializer0 { 956*f1fbf3c2SXin Li private ASTree expression; 957*f1fbf3c2SXin Li PtreeInitializer(ASTree expr)958*f1fbf3c2SXin Li PtreeInitializer(ASTree expr) { expression = expr; } 959*f1fbf3c2SXin Li 960*f1fbf3c2SXin Li @Override compileExpr(Javac drv)961*f1fbf3c2SXin Li void compileExpr(Javac drv) throws CompileError { 962*f1fbf3c2SXin Li drv.compileExpr(expression); 963*f1fbf3c2SXin Li } 964*f1fbf3c2SXin Li 965*f1fbf3c2SXin Li @Override getConstantValue(ConstPool cp, CtClass type)966*f1fbf3c2SXin Li int getConstantValue(ConstPool cp, CtClass type) { 967*f1fbf3c2SXin Li return getConstantValue2(cp, type, expression); 968*f1fbf3c2SXin Li } 969*f1fbf3c2SXin Li } 970*f1fbf3c2SXin Li 971*f1fbf3c2SXin Li /** 972*f1fbf3c2SXin Li * A field initialized with a parameter passed to the constructor 973*f1fbf3c2SXin Li * of the class containing that field. 974*f1fbf3c2SXin Li */ 975*f1fbf3c2SXin Li static class ParamInitializer extends Initializer { 976*f1fbf3c2SXin Li int nthParam; 977*f1fbf3c2SXin Li ParamInitializer()978*f1fbf3c2SXin Li ParamInitializer() {} 979*f1fbf3c2SXin Li 980*f1fbf3c2SXin Li @Override compile(CtClass type, String name, Bytecode code, CtClass[] parameters, Javac drv)981*f1fbf3c2SXin Li int compile(CtClass type, String name, Bytecode code, 982*f1fbf3c2SXin Li CtClass[] parameters, Javac drv) 983*f1fbf3c2SXin Li throws CannotCompileException 984*f1fbf3c2SXin Li { 985*f1fbf3c2SXin Li if (parameters != null && nthParam < parameters.length) { 986*f1fbf3c2SXin Li code.addAload(0); 987*f1fbf3c2SXin Li int nth = nthParamToLocal(nthParam, parameters, false); 988*f1fbf3c2SXin Li int s = code.addLoad(nth, type) + 1; 989*f1fbf3c2SXin Li code.addPutfield(Bytecode.THIS, name, Descriptor.of(type)); 990*f1fbf3c2SXin Li return s; // stack size 991*f1fbf3c2SXin Li } 992*f1fbf3c2SXin Li return 0; // do not initialize 993*f1fbf3c2SXin Li } 994*f1fbf3c2SXin Li 995*f1fbf3c2SXin Li /** 996*f1fbf3c2SXin Li * Computes the index of the local variable that the n-th parameter 997*f1fbf3c2SXin Li * is assigned to. 998*f1fbf3c2SXin Li * 999*f1fbf3c2SXin Li * @param nth n-th parameter 1000*f1fbf3c2SXin Li * @param params list of parameter types 1001*f1fbf3c2SXin Li * @param isStatic true if the method is static. 1002*f1fbf3c2SXin Li */ nthParamToLocal(int nth, CtClass[] params, boolean isStatic)1003*f1fbf3c2SXin Li static int nthParamToLocal(int nth, CtClass[] params, 1004*f1fbf3c2SXin Li boolean isStatic) { 1005*f1fbf3c2SXin Li CtClass longType = CtClass.longType; 1006*f1fbf3c2SXin Li CtClass doubleType = CtClass.doubleType; 1007*f1fbf3c2SXin Li int k; 1008*f1fbf3c2SXin Li if (isStatic) 1009*f1fbf3c2SXin Li k = 0; 1010*f1fbf3c2SXin Li else 1011*f1fbf3c2SXin Li k = 1; // 0 is THIS. 1012*f1fbf3c2SXin Li 1013*f1fbf3c2SXin Li for (int i = 0; i < nth; ++i) { 1014*f1fbf3c2SXin Li CtClass type = params[i]; 1015*f1fbf3c2SXin Li if (type == longType || type == doubleType) 1016*f1fbf3c2SXin Li k += 2; 1017*f1fbf3c2SXin Li else 1018*f1fbf3c2SXin Li ++k; 1019*f1fbf3c2SXin Li } 1020*f1fbf3c2SXin Li 1021*f1fbf3c2SXin Li return k; 1022*f1fbf3c2SXin Li } 1023*f1fbf3c2SXin Li 1024*f1fbf3c2SXin Li @Override compileIfStatic(CtClass type, String name, Bytecode code, Javac drv)1025*f1fbf3c2SXin Li int compileIfStatic(CtClass type, String name, Bytecode code, 1026*f1fbf3c2SXin Li Javac drv) throws CannotCompileException 1027*f1fbf3c2SXin Li { 1028*f1fbf3c2SXin Li return 0; 1029*f1fbf3c2SXin Li } 1030*f1fbf3c2SXin Li } 1031*f1fbf3c2SXin Li 1032*f1fbf3c2SXin Li /** 1033*f1fbf3c2SXin Li * A field initialized with an object created by the new operator. 1034*f1fbf3c2SXin Li */ 1035*f1fbf3c2SXin Li static class NewInitializer extends Initializer { 1036*f1fbf3c2SXin Li CtClass objectType; 1037*f1fbf3c2SXin Li String[] stringParams; 1038*f1fbf3c2SXin Li boolean withConstructorParams; 1039*f1fbf3c2SXin Li NewInitializer()1040*f1fbf3c2SXin Li NewInitializer() {} 1041*f1fbf3c2SXin Li 1042*f1fbf3c2SXin Li /** 1043*f1fbf3c2SXin Li * Produces codes in which a new object is created and assigned to 1044*f1fbf3c2SXin Li * the field as the initial value. 1045*f1fbf3c2SXin Li */ 1046*f1fbf3c2SXin Li @Override compile(CtClass type, String name, Bytecode code, CtClass[] parameters, Javac drv)1047*f1fbf3c2SXin Li int compile(CtClass type, String name, Bytecode code, 1048*f1fbf3c2SXin Li CtClass[] parameters, Javac drv) 1049*f1fbf3c2SXin Li throws CannotCompileException 1050*f1fbf3c2SXin Li { 1051*f1fbf3c2SXin Li int stacksize; 1052*f1fbf3c2SXin Li 1053*f1fbf3c2SXin Li code.addAload(0); 1054*f1fbf3c2SXin Li code.addNew(objectType); 1055*f1fbf3c2SXin Li code.add(Bytecode.DUP); 1056*f1fbf3c2SXin Li code.addAload(0); 1057*f1fbf3c2SXin Li 1058*f1fbf3c2SXin Li if (stringParams == null) 1059*f1fbf3c2SXin Li stacksize = 4; 1060*f1fbf3c2SXin Li else 1061*f1fbf3c2SXin Li stacksize = compileStringParameter(code) + 4; 1062*f1fbf3c2SXin Li 1063*f1fbf3c2SXin Li if (withConstructorParams) 1064*f1fbf3c2SXin Li stacksize += CtNewWrappedMethod.compileParameterList(code, 1065*f1fbf3c2SXin Li parameters, 1); 1066*f1fbf3c2SXin Li 1067*f1fbf3c2SXin Li code.addInvokespecial(objectType, "<init>", getDescriptor()); 1068*f1fbf3c2SXin Li code.addPutfield(Bytecode.THIS, name, Descriptor.of(type)); 1069*f1fbf3c2SXin Li return stacksize; 1070*f1fbf3c2SXin Li } 1071*f1fbf3c2SXin Li getDescriptor()1072*f1fbf3c2SXin Li private String getDescriptor() { 1073*f1fbf3c2SXin Li final String desc3 1074*f1fbf3c2SXin Li = "(Ljava/lang/Object;[Ljava/lang/String;[Ljava/lang/Object;)V"; 1075*f1fbf3c2SXin Li 1076*f1fbf3c2SXin Li if (stringParams == null) 1077*f1fbf3c2SXin Li if (withConstructorParams) 1078*f1fbf3c2SXin Li return "(Ljava/lang/Object;[Ljava/lang/Object;)V"; 1079*f1fbf3c2SXin Li else 1080*f1fbf3c2SXin Li return "(Ljava/lang/Object;)V"; 1081*f1fbf3c2SXin Li 1082*f1fbf3c2SXin Li if (withConstructorParams) 1083*f1fbf3c2SXin Li return desc3; 1084*f1fbf3c2SXin Li 1085*f1fbf3c2SXin Li return "(Ljava/lang/Object;[Ljava/lang/String;)V"; 1086*f1fbf3c2SXin Li } 1087*f1fbf3c2SXin Li 1088*f1fbf3c2SXin Li /** 1089*f1fbf3c2SXin Li * Produces codes for a static field. 1090*f1fbf3c2SXin Li */ 1091*f1fbf3c2SXin Li @Override compileIfStatic(CtClass type, String name, Bytecode code, Javac drv)1092*f1fbf3c2SXin Li int compileIfStatic(CtClass type, String name, Bytecode code, 1093*f1fbf3c2SXin Li Javac drv) throws CannotCompileException 1094*f1fbf3c2SXin Li { 1095*f1fbf3c2SXin Li String desc; 1096*f1fbf3c2SXin Li 1097*f1fbf3c2SXin Li code.addNew(objectType); 1098*f1fbf3c2SXin Li code.add(Bytecode.DUP); 1099*f1fbf3c2SXin Li 1100*f1fbf3c2SXin Li int stacksize = 2; 1101*f1fbf3c2SXin Li if (stringParams == null) 1102*f1fbf3c2SXin Li desc = "()V"; 1103*f1fbf3c2SXin Li else { 1104*f1fbf3c2SXin Li desc = "([Ljava/lang/String;)V"; 1105*f1fbf3c2SXin Li stacksize += compileStringParameter(code); 1106*f1fbf3c2SXin Li } 1107*f1fbf3c2SXin Li 1108*f1fbf3c2SXin Li code.addInvokespecial(objectType, "<init>", desc); 1109*f1fbf3c2SXin Li code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type)); 1110*f1fbf3c2SXin Li return stacksize; 1111*f1fbf3c2SXin Li } 1112*f1fbf3c2SXin Li compileStringParameter(Bytecode code)1113*f1fbf3c2SXin Li protected final int compileStringParameter(Bytecode code) 1114*f1fbf3c2SXin Li throws CannotCompileException 1115*f1fbf3c2SXin Li { 1116*f1fbf3c2SXin Li int nparam = stringParams.length; 1117*f1fbf3c2SXin Li code.addIconst(nparam); 1118*f1fbf3c2SXin Li code.addAnewarray(javaLangString); 1119*f1fbf3c2SXin Li for (int j = 0; j < nparam; ++j) { 1120*f1fbf3c2SXin Li code.add(Bytecode.DUP); // dup 1121*f1fbf3c2SXin Li code.addIconst(j); // iconst_<j> 1122*f1fbf3c2SXin Li code.addLdc(stringParams[j]); // ldc ... 1123*f1fbf3c2SXin Li code.add(Bytecode.AASTORE); // aastore 1124*f1fbf3c2SXin Li } 1125*f1fbf3c2SXin Li 1126*f1fbf3c2SXin Li return 4; 1127*f1fbf3c2SXin Li } 1128*f1fbf3c2SXin Li 1129*f1fbf3c2SXin Li } 1130*f1fbf3c2SXin Li 1131*f1fbf3c2SXin Li /** 1132*f1fbf3c2SXin Li * A field initialized with the result of a static method call. 1133*f1fbf3c2SXin Li */ 1134*f1fbf3c2SXin Li static class MethodInitializer extends NewInitializer { 1135*f1fbf3c2SXin Li String methodName; 1136*f1fbf3c2SXin Li // the method class is specified by objectType. 1137*f1fbf3c2SXin Li MethodInitializer()1138*f1fbf3c2SXin Li MethodInitializer() {} 1139*f1fbf3c2SXin Li 1140*f1fbf3c2SXin Li /** 1141*f1fbf3c2SXin Li * Produces codes in which a new object is created and assigned to 1142*f1fbf3c2SXin Li * the field as the initial value. 1143*f1fbf3c2SXin Li */ 1144*f1fbf3c2SXin Li @Override compile(CtClass type, String name, Bytecode code, CtClass[] parameters, Javac drv)1145*f1fbf3c2SXin Li int compile(CtClass type, String name, Bytecode code, 1146*f1fbf3c2SXin Li CtClass[] parameters, Javac drv) 1147*f1fbf3c2SXin Li throws CannotCompileException 1148*f1fbf3c2SXin Li { 1149*f1fbf3c2SXin Li int stacksize; 1150*f1fbf3c2SXin Li 1151*f1fbf3c2SXin Li code.addAload(0); 1152*f1fbf3c2SXin Li code.addAload(0); 1153*f1fbf3c2SXin Li 1154*f1fbf3c2SXin Li if (stringParams == null) 1155*f1fbf3c2SXin Li stacksize = 2; 1156*f1fbf3c2SXin Li else 1157*f1fbf3c2SXin Li stacksize = compileStringParameter(code) + 2; 1158*f1fbf3c2SXin Li 1159*f1fbf3c2SXin Li if (withConstructorParams) 1160*f1fbf3c2SXin Li stacksize += CtNewWrappedMethod.compileParameterList(code, 1161*f1fbf3c2SXin Li parameters, 1); 1162*f1fbf3c2SXin Li 1163*f1fbf3c2SXin Li String typeDesc = Descriptor.of(type); 1164*f1fbf3c2SXin Li String mDesc = getDescriptor() + typeDesc; 1165*f1fbf3c2SXin Li code.addInvokestatic(objectType, methodName, mDesc); 1166*f1fbf3c2SXin Li code.addPutfield(Bytecode.THIS, name, typeDesc); 1167*f1fbf3c2SXin Li return stacksize; 1168*f1fbf3c2SXin Li } 1169*f1fbf3c2SXin Li getDescriptor()1170*f1fbf3c2SXin Li private String getDescriptor() { 1171*f1fbf3c2SXin Li final String desc3 1172*f1fbf3c2SXin Li = "(Ljava/lang/Object;[Ljava/lang/String;[Ljava/lang/Object;)"; 1173*f1fbf3c2SXin Li 1174*f1fbf3c2SXin Li if (stringParams == null) 1175*f1fbf3c2SXin Li if (withConstructorParams) 1176*f1fbf3c2SXin Li return "(Ljava/lang/Object;[Ljava/lang/Object;)"; 1177*f1fbf3c2SXin Li else 1178*f1fbf3c2SXin Li return "(Ljava/lang/Object;)"; 1179*f1fbf3c2SXin Li 1180*f1fbf3c2SXin Li if (withConstructorParams) 1181*f1fbf3c2SXin Li return desc3; 1182*f1fbf3c2SXin Li 1183*f1fbf3c2SXin Li return "(Ljava/lang/Object;[Ljava/lang/String;)"; 1184*f1fbf3c2SXin Li } 1185*f1fbf3c2SXin Li 1186*f1fbf3c2SXin Li /** 1187*f1fbf3c2SXin Li * Produces codes for a static field. 1188*f1fbf3c2SXin Li */ 1189*f1fbf3c2SXin Li @Override compileIfStatic(CtClass type, String name, Bytecode code, Javac drv)1190*f1fbf3c2SXin Li int compileIfStatic(CtClass type, String name, Bytecode code, 1191*f1fbf3c2SXin Li Javac drv) throws CannotCompileException 1192*f1fbf3c2SXin Li { 1193*f1fbf3c2SXin Li String desc; 1194*f1fbf3c2SXin Li 1195*f1fbf3c2SXin Li int stacksize = 1; 1196*f1fbf3c2SXin Li if (stringParams == null) 1197*f1fbf3c2SXin Li desc = "()"; 1198*f1fbf3c2SXin Li else { 1199*f1fbf3c2SXin Li desc = "([Ljava/lang/String;)"; 1200*f1fbf3c2SXin Li stacksize += compileStringParameter(code); 1201*f1fbf3c2SXin Li } 1202*f1fbf3c2SXin Li 1203*f1fbf3c2SXin Li String typeDesc = Descriptor.of(type); 1204*f1fbf3c2SXin Li code.addInvokestatic(objectType, methodName, desc + typeDesc); 1205*f1fbf3c2SXin Li code.addPutstatic(Bytecode.THIS, name, typeDesc); 1206*f1fbf3c2SXin Li return stacksize; 1207*f1fbf3c2SXin Li } 1208*f1fbf3c2SXin Li } 1209*f1fbf3c2SXin Li 1210*f1fbf3c2SXin Li static class IntInitializer extends Initializer { 1211*f1fbf3c2SXin Li int value; 1212*f1fbf3c2SXin Li IntInitializer(int v)1213*f1fbf3c2SXin Li IntInitializer(int v) { value = v; } 1214*f1fbf3c2SXin Li 1215*f1fbf3c2SXin Li @Override check(String desc)1216*f1fbf3c2SXin Li void check(String desc) throws CannotCompileException { 1217*f1fbf3c2SXin Li char c = desc.charAt(0); 1218*f1fbf3c2SXin Li if (c != 'I' && c != 'S' && c != 'B' && c != 'C' && c != 'Z') 1219*f1fbf3c2SXin Li throw new CannotCompileException("type mismatch"); 1220*f1fbf3c2SXin Li } 1221*f1fbf3c2SXin Li 1222*f1fbf3c2SXin Li @Override compile(CtClass type, String name, Bytecode code, CtClass[] parameters, Javac drv)1223*f1fbf3c2SXin Li int compile(CtClass type, String name, Bytecode code, 1224*f1fbf3c2SXin Li CtClass[] parameters, Javac drv) 1225*f1fbf3c2SXin Li throws CannotCompileException 1226*f1fbf3c2SXin Li { 1227*f1fbf3c2SXin Li code.addAload(0); 1228*f1fbf3c2SXin Li code.addIconst(value); 1229*f1fbf3c2SXin Li code.addPutfield(Bytecode.THIS, name, Descriptor.of(type)); 1230*f1fbf3c2SXin Li return 2; // stack size 1231*f1fbf3c2SXin Li } 1232*f1fbf3c2SXin Li 1233*f1fbf3c2SXin Li @Override compileIfStatic(CtClass type, String name, Bytecode code, Javac drv)1234*f1fbf3c2SXin Li int compileIfStatic(CtClass type, String name, Bytecode code, 1235*f1fbf3c2SXin Li Javac drv) throws CannotCompileException 1236*f1fbf3c2SXin Li { 1237*f1fbf3c2SXin Li code.addIconst(value); 1238*f1fbf3c2SXin Li code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type)); 1239*f1fbf3c2SXin Li return 1; // stack size 1240*f1fbf3c2SXin Li } 1241*f1fbf3c2SXin Li 1242*f1fbf3c2SXin Li @Override getConstantValue(ConstPool cp, CtClass type)1243*f1fbf3c2SXin Li int getConstantValue(ConstPool cp, CtClass type) { 1244*f1fbf3c2SXin Li return cp.addIntegerInfo(value); 1245*f1fbf3c2SXin Li } 1246*f1fbf3c2SXin Li } 1247*f1fbf3c2SXin Li 1248*f1fbf3c2SXin Li static class LongInitializer extends Initializer { 1249*f1fbf3c2SXin Li long value; 1250*f1fbf3c2SXin Li LongInitializer(long v)1251*f1fbf3c2SXin Li LongInitializer(long v) { value = v; } 1252*f1fbf3c2SXin Li 1253*f1fbf3c2SXin Li @Override check(String desc)1254*f1fbf3c2SXin Li void check(String desc) throws CannotCompileException { 1255*f1fbf3c2SXin Li if (!desc.equals("J")) 1256*f1fbf3c2SXin Li throw new CannotCompileException("type mismatch"); 1257*f1fbf3c2SXin Li } 1258*f1fbf3c2SXin Li 1259*f1fbf3c2SXin Li @Override compile(CtClass type, String name, Bytecode code, CtClass[] parameters, Javac drv)1260*f1fbf3c2SXin Li int compile(CtClass type, String name, Bytecode code, 1261*f1fbf3c2SXin Li CtClass[] parameters, Javac drv) 1262*f1fbf3c2SXin Li throws CannotCompileException 1263*f1fbf3c2SXin Li { 1264*f1fbf3c2SXin Li code.addAload(0); 1265*f1fbf3c2SXin Li code.addLdc2w(value); 1266*f1fbf3c2SXin Li code.addPutfield(Bytecode.THIS, name, Descriptor.of(type)); 1267*f1fbf3c2SXin Li return 3; // stack size 1268*f1fbf3c2SXin Li } 1269*f1fbf3c2SXin Li 1270*f1fbf3c2SXin Li @Override compileIfStatic(CtClass type, String name, Bytecode code, Javac drv)1271*f1fbf3c2SXin Li int compileIfStatic(CtClass type, String name, Bytecode code, 1272*f1fbf3c2SXin Li Javac drv) throws CannotCompileException 1273*f1fbf3c2SXin Li { 1274*f1fbf3c2SXin Li code.addLdc2w(value); 1275*f1fbf3c2SXin Li code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type)); 1276*f1fbf3c2SXin Li return 2; // stack size 1277*f1fbf3c2SXin Li } 1278*f1fbf3c2SXin Li 1279*f1fbf3c2SXin Li @Override getConstantValue(ConstPool cp, CtClass type)1280*f1fbf3c2SXin Li int getConstantValue(ConstPool cp, CtClass type) { 1281*f1fbf3c2SXin Li if (type == CtClass.longType) 1282*f1fbf3c2SXin Li return cp.addLongInfo(value); 1283*f1fbf3c2SXin Li return 0; 1284*f1fbf3c2SXin Li } 1285*f1fbf3c2SXin Li } 1286*f1fbf3c2SXin Li 1287*f1fbf3c2SXin Li static class FloatInitializer extends Initializer { 1288*f1fbf3c2SXin Li float value; 1289*f1fbf3c2SXin Li FloatInitializer(float v)1290*f1fbf3c2SXin Li FloatInitializer(float v) { value = v; } 1291*f1fbf3c2SXin Li 1292*f1fbf3c2SXin Li @Override check(String desc)1293*f1fbf3c2SXin Li void check(String desc) throws CannotCompileException { 1294*f1fbf3c2SXin Li if (!desc.equals("F")) 1295*f1fbf3c2SXin Li throw new CannotCompileException("type mismatch"); 1296*f1fbf3c2SXin Li } 1297*f1fbf3c2SXin Li 1298*f1fbf3c2SXin Li @Override compile(CtClass type, String name, Bytecode code, CtClass[] parameters, Javac drv)1299*f1fbf3c2SXin Li int compile(CtClass type, String name, Bytecode code, 1300*f1fbf3c2SXin Li CtClass[] parameters, Javac drv) 1301*f1fbf3c2SXin Li throws CannotCompileException 1302*f1fbf3c2SXin Li { 1303*f1fbf3c2SXin Li code.addAload(0); 1304*f1fbf3c2SXin Li code.addFconst(value); 1305*f1fbf3c2SXin Li code.addPutfield(Bytecode.THIS, name, Descriptor.of(type)); 1306*f1fbf3c2SXin Li return 3; // stack size 1307*f1fbf3c2SXin Li } 1308*f1fbf3c2SXin Li 1309*f1fbf3c2SXin Li @Override compileIfStatic(CtClass type, String name, Bytecode code, Javac drv)1310*f1fbf3c2SXin Li int compileIfStatic(CtClass type, String name, Bytecode code, 1311*f1fbf3c2SXin Li Javac drv) throws CannotCompileException 1312*f1fbf3c2SXin Li { 1313*f1fbf3c2SXin Li code.addFconst(value); 1314*f1fbf3c2SXin Li code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type)); 1315*f1fbf3c2SXin Li return 2; // stack size 1316*f1fbf3c2SXin Li } 1317*f1fbf3c2SXin Li 1318*f1fbf3c2SXin Li @Override getConstantValue(ConstPool cp, CtClass type)1319*f1fbf3c2SXin Li int getConstantValue(ConstPool cp, CtClass type) { 1320*f1fbf3c2SXin Li if (type == CtClass.floatType) 1321*f1fbf3c2SXin Li return cp.addFloatInfo(value); 1322*f1fbf3c2SXin Li return 0; 1323*f1fbf3c2SXin Li } 1324*f1fbf3c2SXin Li } 1325*f1fbf3c2SXin Li 1326*f1fbf3c2SXin Li static class DoubleInitializer extends Initializer { 1327*f1fbf3c2SXin Li double value; 1328*f1fbf3c2SXin Li DoubleInitializer(double v)1329*f1fbf3c2SXin Li DoubleInitializer(double v) { value = v; } 1330*f1fbf3c2SXin Li 1331*f1fbf3c2SXin Li @Override check(String desc)1332*f1fbf3c2SXin Li void check(String desc) throws CannotCompileException { 1333*f1fbf3c2SXin Li if (!desc.equals("D")) 1334*f1fbf3c2SXin Li throw new CannotCompileException("type mismatch"); 1335*f1fbf3c2SXin Li } 1336*f1fbf3c2SXin Li 1337*f1fbf3c2SXin Li @Override compile(CtClass type, String name, Bytecode code, CtClass[] parameters, Javac drv)1338*f1fbf3c2SXin Li int compile(CtClass type, String name, Bytecode code, 1339*f1fbf3c2SXin Li CtClass[] parameters, Javac drv) 1340*f1fbf3c2SXin Li throws CannotCompileException 1341*f1fbf3c2SXin Li { 1342*f1fbf3c2SXin Li code.addAload(0); 1343*f1fbf3c2SXin Li code.addLdc2w(value); 1344*f1fbf3c2SXin Li code.addPutfield(Bytecode.THIS, name, Descriptor.of(type)); 1345*f1fbf3c2SXin Li return 3; // stack size 1346*f1fbf3c2SXin Li } 1347*f1fbf3c2SXin Li 1348*f1fbf3c2SXin Li @Override compileIfStatic(CtClass type, String name, Bytecode code, Javac drv)1349*f1fbf3c2SXin Li int compileIfStatic(CtClass type, String name, Bytecode code, 1350*f1fbf3c2SXin Li Javac drv) throws CannotCompileException 1351*f1fbf3c2SXin Li { 1352*f1fbf3c2SXin Li code.addLdc2w(value); 1353*f1fbf3c2SXin Li code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type)); 1354*f1fbf3c2SXin Li return 2; // stack size 1355*f1fbf3c2SXin Li } 1356*f1fbf3c2SXin Li 1357*f1fbf3c2SXin Li @Override getConstantValue(ConstPool cp, CtClass type)1358*f1fbf3c2SXin Li int getConstantValue(ConstPool cp, CtClass type) { 1359*f1fbf3c2SXin Li if (type == CtClass.doubleType) 1360*f1fbf3c2SXin Li return cp.addDoubleInfo(value); 1361*f1fbf3c2SXin Li return 0; 1362*f1fbf3c2SXin Li } 1363*f1fbf3c2SXin Li } 1364*f1fbf3c2SXin Li 1365*f1fbf3c2SXin Li static class StringInitializer extends Initializer { 1366*f1fbf3c2SXin Li String value; 1367*f1fbf3c2SXin Li StringInitializer(String v)1368*f1fbf3c2SXin Li StringInitializer(String v) { value = v; } 1369*f1fbf3c2SXin Li 1370*f1fbf3c2SXin Li @Override compile(CtClass type, String name, Bytecode code, CtClass[] parameters, Javac drv)1371*f1fbf3c2SXin Li int compile(CtClass type, String name, Bytecode code, 1372*f1fbf3c2SXin Li CtClass[] parameters, Javac drv) 1373*f1fbf3c2SXin Li throws CannotCompileException 1374*f1fbf3c2SXin Li { 1375*f1fbf3c2SXin Li code.addAload(0); 1376*f1fbf3c2SXin Li code.addLdc(value); 1377*f1fbf3c2SXin Li code.addPutfield(Bytecode.THIS, name, Descriptor.of(type)); 1378*f1fbf3c2SXin Li return 2; // stack size 1379*f1fbf3c2SXin Li } 1380*f1fbf3c2SXin Li 1381*f1fbf3c2SXin Li @Override compileIfStatic(CtClass type, String name, Bytecode code, Javac drv)1382*f1fbf3c2SXin Li int compileIfStatic(CtClass type, String name, Bytecode code, 1383*f1fbf3c2SXin Li Javac drv) throws CannotCompileException 1384*f1fbf3c2SXin Li { 1385*f1fbf3c2SXin Li code.addLdc(value); 1386*f1fbf3c2SXin Li code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type)); 1387*f1fbf3c2SXin Li return 1; // stack size 1388*f1fbf3c2SXin Li } 1389*f1fbf3c2SXin Li 1390*f1fbf3c2SXin Li @Override getConstantValue(ConstPool cp, CtClass type)1391*f1fbf3c2SXin Li int getConstantValue(ConstPool cp, CtClass type) { 1392*f1fbf3c2SXin Li if (type.getName().equals(javaLangString)) 1393*f1fbf3c2SXin Li return cp.addStringInfo(value); 1394*f1fbf3c2SXin Li return 0; 1395*f1fbf3c2SXin Li } 1396*f1fbf3c2SXin Li } 1397*f1fbf3c2SXin Li 1398*f1fbf3c2SXin Li static class ArrayInitializer extends Initializer { 1399*f1fbf3c2SXin Li CtClass type; 1400*f1fbf3c2SXin Li int size; 1401*f1fbf3c2SXin Li ArrayInitializer(CtClass t, int s)1402*f1fbf3c2SXin Li ArrayInitializer(CtClass t, int s) { type = t; size = s; } 1403*f1fbf3c2SXin Li addNewarray(Bytecode code)1404*f1fbf3c2SXin Li private void addNewarray(Bytecode code) { 1405*f1fbf3c2SXin Li if (type.isPrimitive()) 1406*f1fbf3c2SXin Li code.addNewarray(((CtPrimitiveType)type).getArrayType(), 1407*f1fbf3c2SXin Li size); 1408*f1fbf3c2SXin Li else 1409*f1fbf3c2SXin Li code.addAnewarray(type, size); 1410*f1fbf3c2SXin Li } 1411*f1fbf3c2SXin Li 1412*f1fbf3c2SXin Li @Override compile(CtClass type, String name, Bytecode code, CtClass[] parameters, Javac drv)1413*f1fbf3c2SXin Li int compile(CtClass type, String name, Bytecode code, 1414*f1fbf3c2SXin Li CtClass[] parameters, Javac drv) 1415*f1fbf3c2SXin Li throws CannotCompileException 1416*f1fbf3c2SXin Li { 1417*f1fbf3c2SXin Li code.addAload(0); 1418*f1fbf3c2SXin Li addNewarray(code); 1419*f1fbf3c2SXin Li code.addPutfield(Bytecode.THIS, name, Descriptor.of(type)); 1420*f1fbf3c2SXin Li return 2; // stack size 1421*f1fbf3c2SXin Li } 1422*f1fbf3c2SXin Li 1423*f1fbf3c2SXin Li @Override compileIfStatic(CtClass type, String name, Bytecode code, Javac drv)1424*f1fbf3c2SXin Li int compileIfStatic(CtClass type, String name, Bytecode code, 1425*f1fbf3c2SXin Li Javac drv) throws CannotCompileException 1426*f1fbf3c2SXin Li { 1427*f1fbf3c2SXin Li addNewarray(code); 1428*f1fbf3c2SXin Li code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type)); 1429*f1fbf3c2SXin Li return 1; // stack size 1430*f1fbf3c2SXin Li } 1431*f1fbf3c2SXin Li } 1432*f1fbf3c2SXin Li 1433*f1fbf3c2SXin Li static class MultiArrayInitializer extends Initializer { 1434*f1fbf3c2SXin Li CtClass type; 1435*f1fbf3c2SXin Li int[] dim; 1436*f1fbf3c2SXin Li MultiArrayInitializer(CtClass t, int[] d)1437*f1fbf3c2SXin Li MultiArrayInitializer(CtClass t, int[] d) { type = t; dim = d; } 1438*f1fbf3c2SXin Li 1439*f1fbf3c2SXin Li @Override check(String desc)1440*f1fbf3c2SXin Li void check(String desc) throws CannotCompileException { 1441*f1fbf3c2SXin Li if (desc.charAt(0) != '[') 1442*f1fbf3c2SXin Li throw new CannotCompileException("type mismatch"); 1443*f1fbf3c2SXin Li } 1444*f1fbf3c2SXin Li 1445*f1fbf3c2SXin Li @Override compile(CtClass type, String name, Bytecode code, CtClass[] parameters, Javac drv)1446*f1fbf3c2SXin Li int compile(CtClass type, String name, Bytecode code, 1447*f1fbf3c2SXin Li CtClass[] parameters, Javac drv) 1448*f1fbf3c2SXin Li throws CannotCompileException 1449*f1fbf3c2SXin Li { 1450*f1fbf3c2SXin Li code.addAload(0); 1451*f1fbf3c2SXin Li int s = code.addMultiNewarray(type, dim); 1452*f1fbf3c2SXin Li code.addPutfield(Bytecode.THIS, name, Descriptor.of(type)); 1453*f1fbf3c2SXin Li return s + 1; // stack size 1454*f1fbf3c2SXin Li } 1455*f1fbf3c2SXin Li 1456*f1fbf3c2SXin Li @Override compileIfStatic(CtClass type, String name, Bytecode code, Javac drv)1457*f1fbf3c2SXin Li int compileIfStatic(CtClass type, String name, Bytecode code, 1458*f1fbf3c2SXin Li Javac drv) throws CannotCompileException 1459*f1fbf3c2SXin Li { 1460*f1fbf3c2SXin Li int s = code.addMultiNewarray(type, dim); 1461*f1fbf3c2SXin Li code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type)); 1462*f1fbf3c2SXin Li return s; // stack size 1463*f1fbf3c2SXin Li } 1464*f1fbf3c2SXin Li } 1465*f1fbf3c2SXin Li } 1466