aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/javassist/CtField.java
diff options
context:
space:
mode:
authorpatriot1burke <patriot1burke@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2003-04-22 13:47:06 +0000
committerpatriot1burke <patriot1burke@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2003-04-22 13:47:06 +0000
commit069bceaf72fd0d6ffad14ce4e3e00ca91a280bde (patch)
treeb8230a15d3061c64d5a64bf9efa654d0d6311ff2 /src/main/javassist/CtField.java
parentf610083ba0adbcb3fe92a504015fb26fb5a42530 (diff)
downloadjavassist-069bceaf72fd0d6ffad14ce4e3e00ca91a280bde.tar.gz
javassist-069bceaf72fd0d6ffad14ce4e3e00ca91a280bde.zip
This commit was generated by cvs2svn to compensate for changes in r2, which
included commits to RCS files with non-trunk default branches. git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@6 30ef5769-5b8d-40dd-aea6-55b5d6557bb3
Diffstat (limited to 'src/main/javassist/CtField.java')
-rw-r--r--src/main/javassist/CtField.java1107
1 files changed, 1107 insertions, 0 deletions
diff --git a/src/main/javassist/CtField.java b/src/main/javassist/CtField.java
new file mode 100644
index 00000000..6bb45e9c
--- /dev/null
+++ b/src/main/javassist/CtField.java
@@ -0,0 +1,1107 @@
+/*
+ * This file is part of the Javassist toolkit.
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * either http://www.mozilla.org/MPL/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * The Original Code is Javassist.
+ *
+ * The Initial Developer of the Original Code is Shigeru Chiba. Portions
+ * created by Shigeru Chiba are Copyright (C) 1999-2003 Shigeru Chiba.
+ * All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * The development of this software is supported in part by the PRESTO
+ * program (Sakigake Kenkyu 21) of Japan Science and Technology Corporation.
+ */
+
+package javassist;
+
+import javassist.bytecode.*;
+import javassist.compiler.Javac;
+import javassist.compiler.CompileError;
+import javassist.compiler.ast.ASTree;
+
+/**
+ * An instance of CtField represents a field.
+ *
+ * @see CtClass#getDeclaredFields()
+ */
+public class CtField extends CtMember {
+ protected FieldInfo fieldInfo;
+ CtField next;
+
+ /**
+ * Creates a <code>CtField</code> object.
+ * The created field must be added to a class
+ * with <code>CtClass.addField()</code>.
+ * An initial value of the field is specified
+ * by a <code>CtField.Initializer</code> object.
+ *
+ * <p>If getter and setter methods are needed,
+ * call <code>CtNewMethod.getter()</code> and
+ * <code>CtNewMethod.setter()</code>.
+ *
+ * @param type field type
+ * @param name field name
+ * @param declaring the class to which the field will be added.
+ *
+ * @see CtClass#addField(CtField)
+ * @see CtNewMethod#getter(String,CtField)
+ * @see CtNewMethod#setter(String,CtField)
+ * @see CtField.Initializer
+ */
+ public CtField(CtClass type, String name, CtClass declaring)
+ throws CannotCompileException
+ {
+ this(Descriptor.of(type), name, declaring);
+ }
+
+ /**
+ * Creates a copy of the given field.
+ * The created field must be added to a class
+ * with <code>CtClass.addField()</code>.
+ * An initial value of the field is specified
+ * by a <code>CtField.Initializer</code> object.
+ *
+ * <p>If getter and setter methods are needed,
+ * call <code>CtNewMethod.getter()</code> and
+ * <code>CtNewMethod.setter()</code>.
+ *
+ * @param src the original field
+ * @param declaring the class to which the field will be added.
+ * @see CtNewMethod#getter(String,CtField)
+ * @see CtNewMethod#setter(String,CtField)
+ * @see CtField.Initializer
+ */
+ public CtField(CtField src, CtClass declaring)
+ throws CannotCompileException
+ {
+ this(src.fieldInfo.getDescriptor(), src.fieldInfo.getName(),
+ declaring);
+ }
+
+ private CtField(String typeDesc, String name, CtClass clazz)
+ throws CannotCompileException
+ {
+ super(clazz);
+ next = null;
+ ClassFile cf = clazz.getClassFile2();
+ if (cf == null)
+ throw new CannotCompileException("bad declaring class: "
+ + clazz.getName());
+
+ fieldInfo = new FieldInfo(cf.getConstPool(), name, typeDesc);
+ }
+
+ CtField(FieldInfo fi, CtClass clazz) {
+ super(clazz);
+ fieldInfo = fi;
+ next = null;
+ }
+
+ /* Javac.CtFieldWithInit overrides.
+ */
+ protected ASTree getInitAST() { return null; }
+
+ /* Called by CtClassType.addField().
+ */
+ Initializer getInit() {
+ ASTree tree = getInitAST();
+ if (tree == null)
+ return null;
+ else
+ return Initializer.byExpr(tree);
+ }
+
+ /**
+ * Compiles the given source code and creates a field.
+ * Examples of the source code are:
+ *
+ * <ul><pre>
+ * "public String name;"
+ * "public int k = 3;"</pre></ul>
+ *
+ * <p>Note that the source code ends with <code>';'</code>
+ * (semicolon).
+ *
+ * @param src the source text.
+ * @param declaring the class to which the created field is added.
+ */
+ public static CtField make(String src, CtClass declaring)
+ throws CannotCompileException
+ {
+ Javac compiler = new Javac(declaring);
+ try {
+ CtMember obj = compiler.compile(src);
+ if (obj instanceof CtField)
+ return (CtField)obj; // an instance of Javac.CtFieldWithInit
+ }
+ catch (CompileError e) {
+ throw new CannotCompileException(e);
+ }
+
+ throw new CannotCompileException("not a field");
+ }
+
+ static CtField append(CtField list, CtField tail) {
+ tail.next = null;
+ if (list == null)
+ return tail;
+ else {
+ CtField lst = list;
+ while (lst.next != null)
+ lst = lst.next;
+
+ lst.next = tail;
+ return list;
+ }
+ }
+
+ static int count(CtField f) {
+ int n = 0;
+ while (f != null) {
+ ++n;
+ f = f.next;
+ }
+
+ return n;
+ }
+
+ /**
+ * Returns the FieldInfo representing the field in the class file.
+ */
+ public FieldInfo getFieldInfo() {
+ declaringClass.checkModify();
+ return fieldInfo;
+ }
+
+ /**
+ * Undocumented method. Do not use; internal-use only.
+ */
+ public FieldInfo getFieldInfo2() { return fieldInfo; }
+
+ /**
+ * Returns the class declaring the field.
+ */
+ public CtClass getDeclaringClass() {
+ // this is redundant but for javadoc.
+ return super.getDeclaringClass();
+ }
+
+ /**
+ * Returns the name of the field.
+ */
+ public String getName() {
+ return fieldInfo.getName();
+ }
+
+ /**
+ * Changes the name of the field.
+ */
+ public void setName(String newName) {
+ fieldInfo.setName(newName);
+ }
+
+ /**
+ * Returns the encoded modifiers of the field.
+ *
+ * @see Modifier
+ */
+ public int getModifiers() {
+ return AccessFlag.toModifier(fieldInfo.getAccessFlags());
+ }
+
+ /**
+ * Sets the encoded modifiers of the field.
+ *
+ * @see Modifier
+ */
+ public void setModifiers(int mod) {
+ fieldInfo.setAccessFlags(AccessFlag.of(mod));
+ }
+
+ /**
+ * Returns the type of the field.
+ */
+ public CtClass getType() throws NotFoundException {
+ return Descriptor.toCtClass(fieldInfo.getDescriptor(),
+ declaringClass.getClassPool());
+ }
+
+ /**
+ * Sets the type of the field.
+ */
+ public void setType(CtClass clazz) {
+ declaringClass.checkModify();
+ fieldInfo.setDescriptor(Descriptor.of(clazz));
+ }
+
+ /**
+ * Obtains an attribute with the given name.
+ * If that attribute is not found in the class file, this
+ * method returns null.
+ *
+ * @param name attribute name
+ */
+ public byte[] getAttribute(String name) {
+ AttributeInfo ai = fieldInfo.getAttribute(name);
+ if (ai == null)
+ return null;
+ else
+ return ai.get();
+ }
+
+ /**
+ * Adds an attribute. The attribute is saved in the class file.
+ *
+ * @param name attribute name
+ * @param data attribute value
+ */
+ public void setAttribute(String name, byte[] data) {
+ declaringClass.checkModify();
+ fieldInfo.addAttribute(new AttributeInfo(fieldInfo.getConstPool(),
+ name, data));
+ }
+
+ // inner classes
+
+ /**
+ * Instances of this class specify how to initialize a field.
+ * <code>Initializer</code> is passed to
+ * <code>CtClass.addField()</code> with a <code>CtField</code>.
+ *
+ * <p>This class cannot be instantiated with the <code>new</code> operator.
+ * Factory methods such as <code>byParameter()</code> and
+ * <code>byNew</code>
+ * must be used for the instantiation. They create a new instance with
+ * the given parameters and return it.
+ *
+ * @see CtClass#addField(CtField,CtField.Initializer)
+ */
+ public static abstract class Initializer {
+ /**
+ * Makes an initializer that assigns a constant integer value.
+ * The field must be integer type.
+ */
+ public static Initializer constant(int i) {
+ return new IntInitializer(i);
+ }
+
+ /**
+ * Makes an initializer that assigns a constant long value.
+ * The field must be long type.
+ */
+ public static Initializer constant(long l) {
+ return new LongInitializer(l);
+ }
+
+ /**
+ * Makes an initializer that assigns a constant double value.
+ * The field must be double type.
+ */
+ public static Initializer constant(double d) {
+ return new DoubleInitializer(d);
+ }
+
+ /**
+ * Makes an initializer that assigns a constant string value.
+ * The field must be <code>java.lang.String</code> type.
+ */
+ public static Initializer constant(String s) {
+ return new StringInitializer(s);
+ }
+
+ /**
+ * Makes an initializer using a constructor parameter.
+ *
+ * <p>The initial value is the
+ * N-th parameter given to the constructor of the object including
+ * the field. If the constructor takes less than N parameters,
+ * the field is not initialized.
+ * If the field is static, it is never initialized.
+ *
+ * @param nth the n-th (&gt;= 0) parameter is used as
+ * the initial value.
+ * If nth is 0, then the first parameter is
+ * used.
+ */
+ public static Initializer byParameter(int nth) {
+ ParamInitializer i = new ParamInitializer();
+ i.nthParam = nth;
+ return i;
+ }
+
+ /**
+ * Makes an initializer creating a new object.
+ *
+ * <p>This initializer creates a new object and uses it as the initial
+ * value of the field. The constructor of the created object receives
+ * the parameter:
+ *
+ * <ul><code>Object obj</code> - the object including the field.<br>
+ * </ul>
+ *
+ * <p>If the initialized field is static, then the constructor does
+ * not receive any parameters.
+ *
+ * @param objectType the class instantiated for the initial value.
+ */
+ public static Initializer byNew(CtClass objectType) {
+ NewInitializer i = new NewInitializer();
+ i.objectType = objectType;
+ i.stringParams = null;
+ i.withConstructorParams = false;
+ return i;
+ }
+
+ /**
+ * Makes an initializer creating a new object.
+ *
+ * <p>This initializer creates a new object and uses it as the initial
+ * value of the field. The constructor of the created object receives
+ * the parameters:
+ *
+ * <ul><code>Object obj</code> - the object including the field.<br>
+ * <code>String[] strs</code> - the character strings specified
+ * by <code>stringParams</code><br>
+ * </ul>
+ *
+ * <p>If the initialized field is static, then the constructor
+ * receives only <code>strs</code>.
+ *
+ * @param objectType the class instantiated for the initial value.
+ * @param stringParams the array of strings passed to the
+ * constructor.
+ */
+ public static Initializer byNew(CtClass objectType,
+ String[] stringParams) {
+ NewInitializer i = new NewInitializer();
+ i.objectType = objectType;
+ i.stringParams = stringParams;
+ i.withConstructorParams = false;
+ return i;
+ }
+
+ /**
+ * Makes an initializer creating a new object.
+ *
+ * <p>This initializer creates a new object and uses it as the initial
+ * value of the field. The constructor of the created object receives
+ * the parameters:
+ *
+ * <ul><code>Object obj</code> - the object including the field.<br>
+ * <code>Object[] args</code> - the parameters passed to the
+ * constructor of the object including the
+ * filed.
+ * </ul>
+ *
+ * <p>If the initialized field is static, then the constructor does
+ * not receive any parameters.
+ *
+ * @param objectType the class instantiated for the initial value.
+ *
+ * @see javassist.CtField.Initializer#byNewArray(CtClass,int)
+ * @see javassist.CtField.Initializer#byNewArray(CtClass,int[])
+ */
+ public static Initializer byNewWithParams(CtClass objectType) {
+ NewInitializer i = new NewInitializer();
+ i.objectType = objectType;
+ i.stringParams = null;
+ i.withConstructorParams = true;
+ return i;
+ }
+
+ /**
+ * Makes an initializer creating a new object.
+ *
+ * <p>This initializer creates a new object and uses it as the initial
+ * value of the field. The constructor of the created object receives
+ * the parameters:
+ *
+ * <ul><code>Object obj</code> - the object including the field.<br>
+ * <code>String[] strs</code> - the character strings specified
+ * by <code>stringParams</code><br>
+ * <code>Object[] args</code> - the parameters passed to the
+ * constructor of the object including the
+ * filed.
+ * </ul>
+ *
+ * <p>If the initialized field is static, then the constructor receives
+ * only <code>strs</code>.
+ *
+ * @param objectType the class instantiated for the initial value.
+ * @param stringParams the array of strings passed to the
+ * constructor.
+ */
+ public static Initializer byNewWithParams(CtClass objectType,
+ String[] stringParams) {
+ NewInitializer i = new NewInitializer();
+ i.objectType = objectType;
+ i.stringParams = stringParams;
+ i.withConstructorParams = true;
+ return i;
+ }
+
+ /**
+ * Makes an initializer calling a static method.
+ *
+ * <p>This initializer calls a static method and uses the returned
+ * value as the initial value of the field.
+ * The called method receives the parameters:
+ *
+ * <ul><code>Object obj</code> - the object including the field.<br>
+ * </ul>
+ *
+ * <p>If the initialized field is static, then the method does
+ * not receive any parameters.
+ *
+ * <p>The type of the returned value must be the same as the field
+ * type.
+ *
+ * @param methodClass the class that the static method is
+ * declared in.
+ * @param methodName the name of the satic method.
+ */
+ public static Initializer byCall(CtClass methodClass,
+ String methodName) {
+ MethodInitializer i = new MethodInitializer();
+ i.objectType = methodClass;
+ i.methodName = methodName;
+ i.stringParams = null;
+ i.withConstructorParams = false;
+ return i;
+ }
+
+ /**
+ * Makes an initializer calling a static method.
+ *
+ * <p>This initializer calls a static method and uses the returned
+ * value as the initial value of the field. The called method
+ * receives the parameters:
+ *
+ * <ul><code>Object obj</code> - the object including the field.<br>
+ * <code>String[] strs</code> - the character strings specified
+ * by <code>stringParams</code><br>
+ * </ul>
+ *
+ * <p>If the initialized field is static, then the method
+ * receive only <code>strs</code>.
+ *
+ * <p>The type of the returned value must be the same as the field
+ * type.
+ *
+ * @param methodClass the class that the static method is
+ * declared in.
+ * @param methodName the name of the satic method.
+ * @param stringParams the array of strings passed to the
+ * static method.
+ */
+ public static Initializer byCall(CtClass methodClass,
+ String methodName,
+ String[] stringParams) {
+ MethodInitializer i = new MethodInitializer();
+ i.objectType = methodClass;
+ i.methodName = methodName;
+ i.stringParams = stringParams;
+ i.withConstructorParams = false;
+ return i;
+ }
+
+ /**
+ * Makes an initializer calling a static method.
+ *
+ * <p>This initializer calls a static method and uses the returned
+ * value as the initial value of the field. The called method
+ * receives the parameters:
+ *
+ * <ul><code>Object obj</code> - the object including the field.<br>
+ * <code>Object[] args</code> - the parameters passed to the
+ * constructor of the object including the
+ * filed.
+ * </ul>
+ *
+ * <p>If the initialized field is static, then the method does
+ * not receive any parameters.
+ *
+ * <p>The type of the returned value must be the same as the field
+ * type.
+ *
+ * @param methodClass the class that the static method is
+ * declared in.
+ * @param methodName the name of the satic method.
+ */
+ public static Initializer byCallWithParams(CtClass methodClass,
+ String methodName) {
+ MethodInitializer i = new MethodInitializer();
+ i.objectType = methodClass;
+ i.methodName = methodName;
+ i.stringParams = null;
+ i.withConstructorParams = true;
+ return i;
+ }
+
+ /**
+ * Makes an initializer calling a static method.
+ *
+ * <p>This initializer calls a static method and uses the returned
+ * value as the initial value of the field. The called method
+ * receives the parameters:
+ *
+ * <ul><code>Object obj</code> - the object including the field.<br>
+ * <code>String[] strs</code> - the character strings specified
+ * by <code>stringParams</code><br>
+ * <code>Object[] args</code> - the parameters passed to the
+ * constructor of the object including the
+ * filed.
+ * </ul>
+ *
+ * <p>If the initialized field is static, then the method
+ * receive only <code>strs</code>.
+ *
+ * <p>The type of the returned value must be the same as the field
+ * type.
+ *
+ * @param methodClass the class that the static method is
+ * declared in.
+ * @param methodName the name of the satic method.
+ * @param stringParams the array of strings passed to the
+ * static method.
+ */
+ public static Initializer byCallWithParams(CtClass methodClass,
+ String methodName, String[] stringParams) {
+ MethodInitializer i = new MethodInitializer();
+ i.objectType = methodClass;
+ i.methodName = methodName;
+ i.stringParams = stringParams;
+ i.withConstructorParams = true;
+ return i;
+ }
+
+ /**
+ * Makes an initializer creating a new array.
+ *
+ * @param type the type of the array.
+ * @param size the size of the array.
+ * @throws NotFoundException if the type of the array components
+ * is not found.
+ */
+ public static Initializer byNewArray(CtClass type, int size)
+ throws NotFoundException
+ {
+ return new ArrayInitializer(type.getComponentType(), size);
+ }
+
+ /**
+ * Makes an initializer creating a new multi-dimensional array.
+ *
+ * @param type the type of the array.
+ * @param sizes an <code>int</code> array of the size in every
+ * dimension.
+ * The first element is the size in the first
+ * dimension. The second is in the second, etc.
+ */
+ public static Initializer byNewArray(CtClass type, int[] sizes) {
+ return new MultiArrayInitializer(type, sizes);
+ }
+
+ /**
+ * Makes an initializer.
+ *
+ * @param source initializer expression.
+ */
+ public static Initializer byExpr(String source) {
+ return new CodeInitializer(source);
+ }
+
+ static Initializer byExpr(ASTree source) {
+ return new PtreeInitializer(source);
+ }
+
+ // Check whether this initializer is valid for the field type.
+ // If it is invaild, this method throws an exception.
+ void check(CtClass type) throws CannotCompileException {}
+
+ // produce codes for initialization
+ abstract int compile(CtClass type, String name, Bytecode code,
+ CtClass[] parameters, Javac drv)
+ throws CannotCompileException;
+
+ // produce codes for initialization
+ abstract int compileIfStatic(CtClass type, String name,
+ Bytecode code, Javac drv) throws CannotCompileException;
+ }
+
+ static abstract class CodeInitializer0 extends Initializer {
+ abstract void compileExpr(Javac drv) throws CompileError;
+
+ int compile(CtClass type, String name, Bytecode code,
+ CtClass[] parameters, Javac drv)
+ throws CannotCompileException
+ {
+ try {
+ code.addAload(0);
+ compileExpr(drv);
+ code.addPutfield(Bytecode.THIS, name, Descriptor.of(type));
+ return code.getMaxStack();
+ }
+ catch (CompileError e) {
+ throw new CannotCompileException(e);
+ }
+ }
+
+ int compileIfStatic(CtClass type, String name, Bytecode code,
+ Javac drv) throws CannotCompileException
+ {
+ try {
+ compileExpr(drv);
+ code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type));
+ return code.getMaxStack();
+ }
+ catch (CompileError e) {
+ throw new CannotCompileException(e);
+ }
+ }
+ }
+
+ static class CodeInitializer extends CodeInitializer0 {
+ private String expression;
+
+ CodeInitializer(String expr) { expression = expr; }
+
+ void compileExpr(Javac drv) throws CompileError {
+ drv.compileExpr(expression);
+ }
+ }
+
+ static class PtreeInitializer extends CodeInitializer0 {
+ private ASTree expression;
+
+ PtreeInitializer(ASTree expr) { expression = expr; }
+
+ void compileExpr(Javac drv) throws CompileError {
+ drv.compileExpr(expression);
+ }
+ }
+
+ /**
+ * A field initialized with a parameter passed to the constructor
+ * of the class containing that field.
+ */
+ static class ParamInitializer extends Initializer {
+ int nthParam;
+
+ ParamInitializer() {}
+
+ int compile(CtClass type, String name, Bytecode code,
+ CtClass[] parameters, Javac drv)
+ throws CannotCompileException
+ {
+ if (parameters != null && nthParam < parameters.length) {
+ code.addAload(0);
+ int nth = nthParamToLocal(nthParam, parameters, false);
+ int s = code.addLoad(nth, type) + 1;
+ code.addPutfield(Bytecode.THIS, name, Descriptor.of(type));
+ return s; // stack size
+ }
+ else
+ return 0; // do not initialize
+ }
+
+ /**
+ * Computes the index of the local variable that the n-th parameter
+ * is assigned to.
+ *
+ * @param nth n-th parameter
+ * @param params list of parameter types
+ * @param isStatic true if the method is static.
+ */
+ static int nthParamToLocal(int nth, CtClass[] params,
+ boolean isStatic) {
+ CtClass longType = CtClass.longType;
+ CtClass doubleType = CtClass.doubleType;
+ int k;
+ if (isStatic)
+ k = 0;
+ else
+ k = 1; // 0 is THIS.
+
+ for (int i = 0; i < nth; ++i) {
+ CtClass type = params[i];
+ if (type == longType || type == doubleType)
+ k += 2;
+ else
+ ++k;
+ }
+
+ return k;
+ }
+
+ int compileIfStatic(CtClass type, String name, Bytecode code,
+ Javac drv) throws CannotCompileException
+ {
+ return 0;
+ }
+ }
+
+ /**
+ * A field initialized with an object created by the new operator.
+ */
+ static class NewInitializer extends Initializer {
+ CtClass objectType;
+ String[] stringParams;
+ boolean withConstructorParams;
+
+ NewInitializer() {}
+
+ /**
+ * Produces codes in which a new object is created and assigned to
+ * the field as the initial value.
+ */
+ int compile(CtClass type, String name, Bytecode code,
+ CtClass[] parameters, Javac drv)
+ throws CannotCompileException
+ {
+ int stacksize;
+
+ code.addAload(0);
+ code.addNew(objectType);
+ code.add(Bytecode.DUP);
+ code.addAload(0);
+
+ if (stringParams == null)
+ stacksize = 4;
+ else
+ stacksize = compileStringParameter(code) + 4;
+
+ if (withConstructorParams)
+ stacksize += CtNewWrappedMethod.compileParameterList(code,
+ parameters, 1);
+
+ code.addInvokespecial(objectType, "<init>", getDescriptor());
+ code.addPutfield(Bytecode.THIS, name, Descriptor.of(type));
+ return stacksize;
+ }
+
+ private String getDescriptor() {
+ final String desc3
+ = "(Ljava/lang/Object;[Ljava/lang/String;[Ljava/lang/Object;)V";
+
+ if (stringParams == null)
+ if (withConstructorParams)
+ return "(Ljava/lang/Object;[Ljava/lang/Object;)V";
+ else
+ return "(Ljava/lang/Object;)V";
+ else
+ if (withConstructorParams)
+ return desc3;
+ else
+ return "(Ljava/lang/Object;[Ljava/lang/String;)V";
+ }
+
+ /**
+ * Produces codes for a static field.
+ */
+ int compileIfStatic(CtClass type, String name, Bytecode code,
+ Javac drv) throws CannotCompileException
+ {
+ String desc;
+
+ code.addNew(objectType);
+ code.add(Bytecode.DUP);
+
+ int stacksize = 2;
+ if (stringParams == null)
+ desc = "()V";
+ else {
+ desc = "([Ljava/lang/String;)V";
+ stacksize += compileStringParameter(code);
+ }
+
+ code.addInvokespecial(objectType, "<init>", desc);
+ code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type));
+ return stacksize;
+ }
+
+ protected final int compileStringParameter(Bytecode code)
+ throws CannotCompileException
+ {
+ int nparam = stringParams.length;
+ code.addIconst(nparam);
+ code.addAnewarray("java.lang.String");
+ for (int j = 0; j < nparam; ++j) {
+ code.add(Bytecode.DUP); // dup
+ code.addIconst(j); // iconst_<j>
+ code.addLdc(stringParams[j]); // ldc ...
+ code.add(Bytecode.AASTORE); // aastore
+ }
+
+ return 4;
+ }
+
+ }
+
+ /**
+ * A field initialized with the result of a static method call.
+ */
+ static class MethodInitializer extends NewInitializer {
+ String methodName;
+ // the method class is specified by objectType.
+
+ MethodInitializer() {}
+
+ /**
+ * Produces codes in which a new object is created and assigned to
+ * the field as the initial value.
+ */
+ int compile(CtClass type, String name, Bytecode code,
+ CtClass[] parameters, Javac drv)
+ throws CannotCompileException
+ {
+ int stacksize;
+
+ code.addAload(0);
+ code.addAload(0);
+
+ if (stringParams == null)
+ stacksize = 2;
+ else
+ stacksize = compileStringParameter(code) + 2;
+
+ if (withConstructorParams)
+ stacksize += CtNewWrappedMethod.compileParameterList(code,
+ parameters, 1);
+
+ String typeDesc = Descriptor.of(type);
+ String mDesc = getDescriptor() + typeDesc;
+ code.addInvokestatic(objectType, methodName, mDesc);
+ code.addPutfield(Bytecode.THIS, name, typeDesc);
+ return stacksize;
+ }
+
+ private String getDescriptor() {
+ final String desc3
+ = "(Ljava/lang/Object;[Ljava/lang/String;[Ljava/lang/Object;)";
+
+ if (stringParams == null)
+ if (withConstructorParams)
+ return "(Ljava/lang/Object;[Ljava/lang/Object;)";
+ else
+ return "(Ljava/lang/Object;)";
+ else
+ if (withConstructorParams)
+ return desc3;
+ else
+ return "(Ljava/lang/Object;[Ljava/lang/String;)";
+ }
+
+ /**
+ * Produces codes for a static field.
+ */
+ int compileIfStatic(CtClass type, String name, Bytecode code,
+ Javac drv) throws CannotCompileException
+ {
+ String desc;
+
+ int stacksize = 1;
+ if (stringParams == null)
+ desc = "()";
+ else {
+ desc = "([Ljava/lang/String;)";
+ stacksize += compileStringParameter(code);
+ }
+
+ String typeDesc = Descriptor.of(type);
+ code.addInvokestatic(objectType, methodName, desc + typeDesc);
+ code.addPutstatic(Bytecode.THIS, name, typeDesc);
+ return stacksize;
+ }
+ }
+
+ static class IntInitializer extends Initializer {
+ int value;
+
+ IntInitializer(int v) { value = v; }
+
+ void check(CtClass type) throws CannotCompileException {
+ if (type != CtClass.intType)
+ throw new CannotCompileException("type mismatch");
+ }
+
+ int compile(CtClass type, String name, Bytecode code,
+ CtClass[] parameters, Javac drv)
+ throws CannotCompileException
+ {
+ code.addAload(0);
+ code.addIconst(value);
+ code.addPutfield(Bytecode.THIS, name, Descriptor.of(type));
+ return 2; // stack size
+ }
+
+ int compileIfStatic(CtClass type, String name, Bytecode code,
+ Javac drv) throws CannotCompileException
+ {
+ code.addIconst(value);
+ code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type));
+ return 1; // stack size
+ }
+ }
+
+ static class LongInitializer extends Initializer {
+ long value;
+
+ LongInitializer(long v) { value = v; }
+
+ void check(CtClass type) throws CannotCompileException {
+ if (type != CtClass.longType)
+ throw new CannotCompileException("type mismatch");
+ }
+
+ int compile(CtClass type, String name, Bytecode code,
+ CtClass[] parameters, Javac drv)
+ throws CannotCompileException
+ {
+ code.addAload(0);
+ code.addLdc2w(value);
+ code.addPutfield(Bytecode.THIS, name, Descriptor.of(type));
+ return 3; // stack size
+ }
+
+ int compileIfStatic(CtClass type, String name, Bytecode code,
+ Javac drv) throws CannotCompileException
+ {
+ code.addLdc2w(value);
+ code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type));
+ return 2; // stack size
+ }
+ }
+
+ static class DoubleInitializer extends Initializer {
+ double value;
+
+ DoubleInitializer(double v) { value = v; }
+
+ void check(CtClass type) throws CannotCompileException {
+ if (type != CtClass.doubleType)
+ throw new CannotCompileException("type mismatch");
+ }
+
+ int compile(CtClass type, String name, Bytecode code,
+ CtClass[] parameters, Javac drv)
+ throws CannotCompileException
+ {
+ code.addAload(0);
+ code.addLdc2w(value);
+ code.addPutfield(Bytecode.THIS, name, Descriptor.of(type));
+ return 3; // stack size
+ }
+
+ int compileIfStatic(CtClass type, String name, Bytecode code,
+ Javac drv) throws CannotCompileException
+ {
+ code.addLdc2w(value);
+ code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type));
+ return 2; // stack size
+ }
+ }
+
+ static class StringInitializer extends Initializer {
+ String value;
+
+ StringInitializer(String v) { value = v; }
+
+ void check(CtClass type) throws CannotCompileException {
+ if (!type.getName().equals("java.lang.String"))
+ throw new CannotCompileException("type mismatch");
+ }
+
+ int compile(CtClass type, String name, Bytecode code,
+ CtClass[] parameters, Javac drv)
+ throws CannotCompileException
+ {
+ code.addAload(0);
+ code.addLdc(value);
+ code.addPutfield(Bytecode.THIS, name, Descriptor.of(type));
+ return 2; // stack size
+ }
+
+ int compileIfStatic(CtClass type, String name, Bytecode code,
+ Javac drv) throws CannotCompileException
+ {
+ code.addLdc(value);
+ code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type));
+ return 1; // stack size
+ }
+ }
+
+ static class ArrayInitializer extends Initializer {
+ CtClass type;
+ int size;
+
+ ArrayInitializer(CtClass t, int s) { type = t; size = s; }
+
+ private void addNewarray(Bytecode code) {
+ if (type.isPrimitive())
+ code.addNewarray(((CtPrimitiveType)type).getArrayType(),
+ size);
+ else
+ code.addAnewarray(type, size);
+ }
+
+ int compile(CtClass type, String name, Bytecode code,
+ CtClass[] parameters, Javac drv)
+ throws CannotCompileException
+ {
+ code.addAload(0);
+ addNewarray(code);
+ code.addPutfield(Bytecode.THIS, name, Descriptor.of(type));
+ return 2; // stack size
+ }
+
+ int compileIfStatic(CtClass type, String name, Bytecode code,
+ Javac drv) throws CannotCompileException
+ {
+ addNewarray(code);
+ code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type));
+ return 1; // stack size
+ }
+ }
+
+ static class MultiArrayInitializer extends Initializer {
+ CtClass type;
+ int[] dim;
+
+ MultiArrayInitializer(CtClass t, int[] d) { type = t; dim = d; }
+
+ void check(CtClass type) throws CannotCompileException {
+ if (!type.isArray())
+ throw new CannotCompileException("type mismatch");
+ }
+
+ int compile(CtClass type, String name, Bytecode code,
+ CtClass[] parameters, Javac drv)
+ throws CannotCompileException
+ {
+ code.addAload(0);
+ int s = code.addMultiNewarray(type, dim);
+ code.addPutfield(Bytecode.THIS, name, Descriptor.of(type));
+ return s + 1; // stack size
+ }
+
+ int compileIfStatic(CtClass type, String name, Bytecode code,
+ Javac drv) throws CannotCompileException
+ {
+ int s = code.addMultiNewarray(type, dim);
+ code.addPutstatic(Bytecode.THIS, name, Descriptor.of(type));
+ return s; // stack size
+ }
+ }
+}