<h2>Changes</h2>
-<p>- version 3.1
+<p>- version 3.1 RC1
<ul>
+ <li>Better annotation supports. See <code>CtClass.getAnnotations()</code>
<li>javassist.tool.HotSwapper was added.
+ <li>javassist.ClassPool.importPackage() was added.
+ <li>The compiler now accepts array initializers
+ (only one dimensional arrays).
<li>javassist.Dump was moved to javassist.tool.Dump.
</ul>
<project name="javassist" default="jar" basedir=".">
- <property name="dist-version" value="javassist-3.1"/>
+ <property name="dist-version" value="javassist-3.1RC1"/>
<property environment="env"/>
<property name="target.jar" value="javassist.jar"/>
methodInfo.setAccessFlags(AccessFlag.of(mod));
}
+ /**
+ * Returns the annotations associated with this method or constructor.
+ *
+ * @return an array of annotation-type objects.
+ * @see CtMember#getAnnotations()
+ */
+ public Object[] getAnnotations() throws ClassNotFoundException {
+ MethodInfo mi = getMethodInfo2();
+ AnnotationsAttribute ainfo = (AnnotationsAttribute)
+ mi.getAttribute(AnnotationsAttribute.invisibleTag);
+ AnnotationsAttribute ainfo2 = (AnnotationsAttribute)
+ mi.getAttribute(AnnotationsAttribute.visibleTag);
+ return CtClassType.toAnnotationType(getDeclaringClass().getClassPool(),
+ ainfo, ainfo2);
+ }
+
/**
* Obtains parameter types of this method/constructor.
*/
import javassist.bytecode.Opcode;
import javassist.expr.ExprEditor;
-// Subclasses of CtClass: CtClassType, CtPrimitiveType, and CtArray
+/* Note:
+ *
+ * This class is an abstract class and several methods just return null
+ * or throw an exception. Those methods are overridden in subclasses
+ * of this class. Read the source code of CtClassType if you are
+ * interested in the implementation of Javassist.
+ *
+ * Subclasses of CtClass are CtClassType, CtPrimitiveType, and CtArray.
+ */
/**
* An instance of <code>CtClass</code> represents a class.
return 0;
}
+ /**
+ * Returns the annotations associated with this class.
+ * For example, if an annotation <code>@Author</code> is associated
+ * with this class, the returned array contains an <code>Author</code>
+ * object. The member values can be obtained by calling methods on
+ * the <code>Author</code> object.
+ *
+ * @return an array of annotation-type objects.
+ */
+ public Object[] getAnnotations() throws ClassNotFoundException {
+ return new Object[0];
+ }
+
/**
* Sets the modifiers.
*
* <p>This is a convenient method mainly for adding
* a user-defined attribute. For dealing with attributes, see the
* <code>javassist.bytecode</code> package. For example, the following
- * expression adds an attribute of a class file.
+ * expression adds an attribute <code>info</code> to a class file.
*
* <ul><pre>
* getClassFile().addAttribute(info)
import java.util.List;
import javassist.bytecode.AccessFlag;
import javassist.bytecode.AttributeInfo;
+import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.BadBytecode;
import javassist.bytecode.Bytecode;
import javassist.bytecode.ClassFile;
import javassist.bytecode.FieldInfo;
import javassist.bytecode.InnerClassesAttribute;
import javassist.bytecode.MethodInfo;
+import javassist.bytecode.annotation.Annotation;
import javassist.compiler.AccessorMaker;
import javassist.compiler.CompileError;
import javassist.compiler.Javac;
getClassFile2().setAccessFlags(acc);
}
+ public Object[] getAnnotations() throws ClassNotFoundException {
+ ClassFile cf = getClassFile2();
+ AnnotationsAttribute ainfo = (AnnotationsAttribute)
+ cf.getAttribute(AnnotationsAttribute.invisibleTag);
+ AnnotationsAttribute ainfo2 = (AnnotationsAttribute)
+ cf.getAttribute(AnnotationsAttribute.visibleTag);
+ return toAnnotationType(getClassPool(), ainfo, ainfo2);
+ }
+
+ static Object[] toAnnotationType(ClassPool cp, AnnotationsAttribute a1,
+ AnnotationsAttribute a2) throws ClassNotFoundException {
+ Annotation[] anno1, anno2;
+ int size1, size2;
+
+ if (a1 == null) {
+ anno1 = null;
+ size1 = 0;
+ }
+ else {
+ anno1 = a1.getAnnotations();
+ size1 = anno1.length;
+ }
+
+ if (a2 == null) {
+ anno2 = null;
+ size2 = 0;
+ }
+ else {
+ anno2 = a2.getAnnotations();
+ size2 = anno2.length;
+ }
+
+ Object[] result = new Object[size1 + size2];
+ ClassLoader cl = Thread.currentThread().getContextClassLoader();
+ for (int i = 0; i < size1; i++)
+ result[i] = anno1[i].toAnnotationType(cl, cp);
+
+ for (int j = 0; j < size2; j++)
+ result[j + size1] = anno2[j].toAnnotationType(cl, cp);
+
+ return result;
+ }
+
public boolean subclassOf(CtClass superclass) {
if (superclass == null)
return false;
fieldInfo.setAccessFlags(AccessFlag.of(mod));
}
+ /**
+ * Returns the annotations associated with this field.
+ *
+ * @return an array of annotation-type objects.
+ * @see CtMember#getAnnotations()
+ */
+ public Object[] getAnnotations() throws ClassNotFoundException {
+ FieldInfo fi = getFieldInfo2();
+ AnnotationsAttribute ainfo = (AnnotationsAttribute)
+ fi.getAttribute(AnnotationsAttribute.invisibleTag);
+ AnnotationsAttribute ainfo2 = (AnnotationsAttribute)
+ fi.getAttribute(AnnotationsAttribute.visibleTag);
+ return CtClassType.toAnnotationType(getDeclaringClass().getClassPool(),
+ ainfo, ainfo2);
+ }
+
/**
* Returns the type of the field.
*/
*/
public abstract void setModifiers(int mod);
+ /**
+ * Returns the annotations associated with this member.
+ * For example, if an annotation <code>@Author</code> is associated
+ * with this member, the returned array contains an <code>Author</code>
+ * object. The member values can be obtained by calling methods on
+ * the <code>Author</code> object.
+ *
+ * @return an array of annotation-type objects.
+ * @see CtClass#getAnnotations()
+ */
+ public abstract Object[] getAnnotations() throws ClassNotFoundException;
+
/**
* Obtains the name of the member.
*
import javassist.bytecode.ConstPool;
import javassist.bytecode.Descriptor;
+import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
* @return null if the member cannot be found or if the value is
* the default value.
*
- * @see AnnotationDefaultAttribute
+ * @see javassist.bytecode.AnnotationDefaultAttribute
*/
public MemberValue getMemberValue(String name) {
if (members == null)
}
}
+ /**
+ * Constructs an annotation-type object representing this annotation.
+ * For example, if this annotation represents <code>@Author</code>,
+ * this method returns an <code>Author</code> object.
+ *
+ * @param cl class loader for loading an annotation type.
+ * @param cp class pool for obtaining class files.
+ */
+ public Object toAnnotationType(ClassLoader cl, ClassPool cp)
+ throws ClassNotFoundException
+ {
+ return AnnotationImpl.make(cl,
+ MemberValue.loadClass(cl, getTypeName()),
+ cp, this);
+ }
+
/**
* Writes this annotation.
*
--- /dev/null
+/*
+ * Javassist, a Java-bytecode translator toolkit.
+ * Copyright (C) 1999-2005 Shigeru Chiba. All Rights Reserved.
+ *
+ * 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. Alternatively, the contents of this file may be used under
+ * the terms of the GNU Lesser General Public License Version 2.1 or later.
+ *
+ * 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.
+ */
+
+package javassist.bytecode.annotation;
+
+import javassist.ClassPool;
+import javassist.CtClass;
+import javassist.NotFoundException;
+import javassist.bytecode.AnnotationDefaultAttribute;
+import javassist.bytecode.ClassFile;
+import javassist.bytecode.MethodInfo;
+
+import java.lang.reflect.*;
+
+class AnnotationImpl implements InvocationHandler {
+ private Annotation annotation;
+ private ClassPool pool;
+ private ClassLoader classLoader;
+
+ /**
+ * Constructs an annotation object.
+ *
+ * @param cl class loader for obtaining annotation types.
+ * @param clazz the annotation type.
+ * @param cp class pool for containing an annotation
+ * type (or null).
+ * @param anon the annotation.
+ */
+ public static Object make(ClassLoader cl, Class clazz, ClassPool cp,
+ Annotation anon) {
+ AnnotationImpl handler = new AnnotationImpl(anon, cp, cl);
+ return Proxy.newProxyInstance(cl, new Class[] { clazz }, handler);
+ }
+
+ private AnnotationImpl(Annotation a, ClassPool cp, ClassLoader loader) {
+ annotation = a;
+ pool = cp;
+ classLoader = loader;
+ }
+
+ public Object invoke(Object proxy, Method method, Object[] args)
+ throws Throwable
+ {
+ String name = method.getName();
+ MemberValue mv = annotation.getMemberValue(name);
+ if (mv == null)
+ return getDefault(name);
+ else
+ return mv.getValue(classLoader, pool);
+ }
+
+ private Object getDefault(String name)
+ throws ClassNotFoundException, RuntimeException
+ {
+ String classname = annotation.getTypeName();
+ if (pool != null)
+ try {
+ CtClass cc = pool.get(classname);
+ ClassFile cf = cc.getClassFile2();
+ MethodInfo minfo = cf.getMethod(name);
+ if (minfo != null) {
+ AnnotationDefaultAttribute ainfo
+ = (AnnotationDefaultAttribute)
+ minfo.getAttribute(AnnotationDefaultAttribute.tag);
+ if (ainfo != null) {
+ MemberValue mv = ainfo.getDefaultValue();
+ return mv.getValue(classLoader, pool);
+ }
+ }
+ }
+ catch (NotFoundException e) {
+ throw new RuntimeException("cannot find a class file: "
+ + classname);
+ }
+
+ throw new RuntimeException("no default value: " + classname + "."
+ + name + "()");
+ }
+}
*/
package javassist.bytecode.annotation;
+import javassist.ClassPool;
import javassist.bytecode.ConstPool;
import java.io.IOException;
value = a;
}
+ Object getValue(ClassLoader cl, ClassPool cp)
+ throws ClassNotFoundException
+ {
+ return AnnotationImpl.make(cl, getType(cl), cp, value);
+ }
+
+ Class getType(ClassLoader cl) throws ClassNotFoundException {
+ if (value == null)
+ throw new ClassNotFoundException("no type specified");
+ else
+ return loadClass(cl, value.getTypeName());
+ }
+
/**
* Obtains the value.
*/
*/
package javassist.bytecode.annotation;
+import javassist.ClassPool;
import javassist.bytecode.ConstPool;
import java.io.IOException;
+import java.lang.reflect.Array;
/**
* Array member.
values = null;
}
+ Object getValue(ClassLoader cl, ClassPool cp) throws ClassNotFoundException {
+ if (type == null || values == null)
+ throw new ClassNotFoundException("no array elements specified");
+
+ int size = values.length;
+ Object a = Array.newInstance(type.getType(cl), size);
+ for (int i = 0; i < size; i++)
+ Array.set(a, i, values[i].getValue(cl, cp));
+
+ return a;
+ }
+
+ Class getType(ClassLoader cl) throws ClassNotFoundException {
+ if (type == null)
+ throw new ClassNotFoundException("no array type specified");
+
+ Object a = Array.newInstance(type.getType(cl), 0);
+ return a.getClass();
+ }
+
/**
* Obtains the type of the elements.
*
*/
package javassist.bytecode.annotation;
+import javassist.ClassPool;
import javassist.bytecode.ConstPool;
import java.io.IOException;
setValue(false);
}
+ Object getValue(ClassLoader cl, ClassPool cp) {
+ return new Boolean(getValue());
+ }
+
+ Class getType(ClassLoader cl) {
+ return boolean.class;
+ }
+
/**
* Obtains the value of the member.
*/
*/
package javassist.bytecode.annotation;
+import javassist.ClassPool;
import javassist.bytecode.ConstPool;
import java.io.IOException;
setValue((byte)0);
}
+ Object getValue(ClassLoader cl, ClassPool cp) {
+ return new Byte(getValue());
+ }
+
+ Class getType(ClassLoader cl) {
+ return byte.class;
+ }
+
/**
* Obtains the value of the member.
*/
package javassist.bytecode.annotation;
+import javassist.ClassPool;
import javassist.bytecode.ConstPool;
import java.io.IOException;
setValue('\0');
}
+ Object getValue(ClassLoader cl, ClassPool cp) {
+ return new Character(getValue());
+ }
+
+ Class getType(ClassLoader cl) {
+ return char.class;
+ }
+
/**
* Obtains the value of the member.
*/
package javassist.bytecode.annotation;
+import javassist.ClassPool;
import javassist.bytecode.ConstPool;
import javassist.bytecode.Descriptor;
import java.io.IOException;
/**
- * String constant value.
+ * Class value.
*
* @author <a href="mailto:bill@jboss.org">Bill Burke</a>
* @author Shigeru Chiba
int valueIndex;
/**
- * Constructs a string constant value. The initial value is specified
+ * Constructs a class value. The initial value is specified
* by the constant pool entry at the given index.
*
* @param index the index of a CONSTANT_Utf8_info structure.
}
/**
- * Constructs a string constant value.
+ * Constructs a class value.
*
* @param className the initial value.
*/
}
/**
- * Constructs a string constant value.
+ * Constructs a class value.
* The initial value is java.lang.Class.
*/
public ClassMemberValue(ConstPool cp) {
setValue("java.lang.Class");
}
+ Object getValue(ClassLoader cl, ClassPool cp)
+ throws ClassNotFoundException
+ {
+ return loadClass(cl, getValue());
+ }
+
+ Class getType(ClassLoader cl) throws ClassNotFoundException {
+ return loadClass(cl, "java.lang.Class");
+ }
+
/**
* Obtains the value of the member.
*
package javassist.bytecode.annotation;
+import javassist.ClassPool;
import javassist.bytecode.ConstPool;
import java.io.IOException;
*
* @author <a href="mailto:bill@jboss.org">Bill Burke</a>
* @author Shigeru Chiba
- * @version $Revision: 1.5 $
+ * @version $Revision: 1.6 $
*/
public class DoubleMemberValue extends MemberValue {
int valueIndex;
setValue(0.0);
}
+ Object getValue(ClassLoader cl, ClassPool cp) {
+ return new Double(getValue());
+ }
+
+ Class getType(ClassLoader cl) {
+ return double.class;
+ }
+
/**
* Obtains the value of the member.
*/
package javassist.bytecode.annotation;
import java.io.IOException;
+
+import javassist.ClassPool;
import javassist.bytecode.ConstPool;
import javassist.bytecode.Descriptor;
typeIndex = valueIndex = 0;
}
+ Object getValue(ClassLoader cl, ClassPool cp)
+ throws ClassNotFoundException
+ {
+ try {
+ return getType(cl).getField(getValue()).get(null);
+ }
+ catch (NoSuchFieldException e) {
+ throw new ClassNotFoundException(getType() + "." + getValue());
+ }
+ catch (IllegalAccessException e) {
+ throw new ClassNotFoundException(getType() + "." + getValue());
+ }
+ }
+
+ Class getType(ClassLoader cl) throws ClassNotFoundException {
+ return loadClass(cl, getType());
+ }
+
/**
* Obtains the enum type name.
*
package javassist.bytecode.annotation;
+import javassist.ClassPool;
import javassist.bytecode.ConstPool;
import java.io.IOException;
*
* @author <a href="mailto:bill@jboss.org">Bill Burke</a>
* @author Shigeru Chiba
- * @version $Revision: 1.5 $
+ * @version $Revision: 1.6 $
*/
public class FloatMemberValue extends MemberValue {
int valueIndex;
setValue(0.0F);
}
+ Object getValue(ClassLoader cl, ClassPool cp) {
+ return new Float(getValue());
+ }
+
+ Class getType(ClassLoader cl) {
+ return float.class;
+ }
+
/**
* Obtains the value of the member.
*/
package javassist.bytecode.annotation;
+import javassist.ClassPool;
import javassist.bytecode.ConstPool;
import java.io.IOException;
setValue(0);
}
+ Object getValue(ClassLoader cl, ClassPool cp) {
+ return new Integer(getValue());
+ }
+
+ Class getType(ClassLoader cl) {
+ return int.class;
+ }
+
/**
* Obtains the value of the member.
*/
package javassist.bytecode.annotation;
+import javassist.ClassPool;
import javassist.bytecode.ConstPool;
import java.io.IOException;
setValue(0L);
}
+ Object getValue(ClassLoader cl, ClassPool cp) {
+ return new Long(getValue());
+ }
+
+ Class getType(ClassLoader cl) {
+ return long.class;
+ }
+
/**
* Obtains the value of the member.
*/
package javassist.bytecode.annotation;
+import javassist.ClassPool;
import javassist.bytecode.ConstPool;
import java.io.IOException;
this.tag = tag;
}
+ /**
+ * Returns the value. If the value type is a primitive type, the
+ * returned value is boxed.
+ */
+ abstract Object getValue(ClassLoader cl, ClassPool cp)
+ throws ClassNotFoundException;
+
+ abstract Class getType(ClassLoader cl) throws ClassNotFoundException;
+
+ static Class loadClass(ClassLoader cl, String classname)
+ throws ClassNotFoundException
+ {
+ return Class.forName(classname, true, cl);
+ }
+
/**
* Accepts a visitor.
*/
package javassist.bytecode.annotation;
+import javassist.ClassPool;
import javassist.bytecode.ConstPool;
import java.io.IOException;
setValue((short)0);
}
+ Object getValue(ClassLoader cl, ClassPool cp) {
+ return new Short(getValue());
+ }
+
+ Class getType(ClassLoader cl) {
+ return short.class;
+ }
+
/**
* Obtains the value of the member.
*/
package javassist.bytecode.annotation;
+import javassist.ClassPool;
import javassist.bytecode.ConstPool;
import java.io.IOException;
setValue("");
}
+ Object getValue(ClassLoader cl, ClassPool cp) {
+ return getValue();
+ }
+
+ Class getType(ClassLoader cl) {
+ return String.class;
+ }
+
/**
* Obtains the value of the member.
*/
*/
ASTree init = d.getInitializer();
if (init != null) {
- doTypeCheck(init);
+ doTypeCheck(init);
atVariableAssign(null, '=', null, d, init, false);
}
}
public abstract void atNewExpr(NewExpr n) throws CompileError;
+ public abstract void atArrayInit(ArrayInit init) throws CompileError;
+
public void atAssignExpr(AssignExpr expr) throws CompileError {
atAssignExpr(expr, true);
}
if (op != '=')
atVariable(var);
- atAssignCore(expr, op, right, varType, varArray, varClass);
+ // expr is null if the caller is atDeclarator().
+ if (expr == null && right instanceof ArrayInit)
+ atArrayVariableAssign((ArrayInit)right, varType, varArray, varClass);
+ else
+ atAssignCore(expr, op, right, varType, varArray, varClass);
if (doDup)
if (is2word(varType, varArray))
className = varClass;
}
+ protected abstract void atArrayVariableAssign(ArrayInit init,
+ int varType, int varArray, String varClass) throws CompileError;
+
private void atArrayAssign(Expr expr, int op, Expr array,
ASTree right, boolean doDup) throws CompileError
{
import javassist.*;
import javassist.bytecode.*;
import javassist.compiler.ast.*;
+
import java.util.ArrayList;
/* Code generator methods depending on javassist.* classes.
protected boolean resultStatic;
- public MemberCodeGen(Bytecode b, CtClass cc, ClassPool cp)
- {
+ public MemberCodeGen(Bytecode b, CtClass cc, ClassPool cp) {
super(b);
resolver = new MemberResolver(cp);
thisClass = cc;
}
public void atNewArrayExpr(NewExpr expr) throws CompileError {
- if (expr.getInitializer() != null)
- throw new CompileError("array initializer is not supported");
-
int type = expr.getArrayType();
ASTList size = expr.getArraySize();
ASTList classname = expr.getClassName();
+ ArrayInit init = expr.getInitializer();
if (size.length() > 1) {
+ if (init != null)
+ throw new CompileError(
+ "sorry, multi-dimensional array initializer " +
+ "for new is not supported");
+
atMultiNewArray(type, classname, size);
return;
}
- size.head().accept(this);
- exprType = type;
- arrayDim = 1;
+ ASTree sizeExpr = size.head();
+ atNewArrayExpr2(type, sizeExpr, Declarator.astToClassName(classname, '/'), init);
+ }
+
+ private void atNewArrayExpr2(int type, ASTree sizeExpr,
+ String jvmClassname, ArrayInit init) throws CompileError {
+ if (init == null)
+ if (sizeExpr == null)
+ throw new CompileError("no array size");
+ else
+ sizeExpr.accept(this);
+ else
+ if (sizeExpr == null) {
+ int s = init.length();
+ bytecode.addIconst(s);
+ }
+ else
+ throw new CompileError("unnecessary array size specified for new");
+
+ String elementClass;
if (type == CLASS) {
- className = resolveClassName(classname);
- bytecode.addAnewarray(MemberResolver.jvmToJavaName(className));
+ elementClass = resolveClassName(jvmClassname);
+ bytecode.addAnewarray(MemberResolver.jvmToJavaName(elementClass));
}
else {
- className = null;
+ elementClass = null;
int atype = 0;
switch (type) {
case BOOLEAN :
bytecode.addOpcode(NEWARRAY);
bytecode.add(atype);
}
+
+ if (init != null) {
+ int s = init.length();
+ ASTList list = init;
+ for (int i = 0; i < s; i++) {
+ bytecode.addOpcode(DUP);
+ bytecode.addIconst(i);
+ list.head().accept(this);
+ if (!isRefType(type))
+ atNumCastExpr(exprType, type);
+
+ bytecode.addOpcode(getArrayWriteOp(type, 0));
+ list = list.tail();
+ }
+ }
+
+ exprType = type;
+ arrayDim = 1;
+ className = elementClass;
}
private static void badNewExpr() throws CompileError {
throw new CompileError("bad new expression");
}
+ protected void atArrayVariableAssign(ArrayInit init, int varType,
+ int varArray, String varClass) throws CompileError {
+ atNewArrayExpr2(varType, null, varClass, init);
+ }
+
+ public void atArrayInit(ArrayInit init) throws CompileError {
+ throw new CompileError("array initializer is not supported");
+ }
+
protected void atMultiNewArray(int type, ASTList classname, ASTList size)
throws CompileError
{
/* array.initializer :
* '{' (( array.initializer | expression ) ',')* '}'
*/
- private ASTree parseArrayInitializer(SymbolTable tbl)
+ private ArrayInit parseArrayInitializer(SymbolTable tbl)
throws CompileError
{
lex.get(); // '{'
- throw new CompileError("array initializer is not supported", lex);
+ ASTree expr = parseExpression(tbl);
+ ArrayInit init = new ArrayInit(expr);
+ while (lex.lookAhead() == ',') {
+ lex.get();
+ expr = parseExpression(tbl);
+ ASTList.append(init, expr);
+ }
+
+ if (lex.get() != '}')
+ throw new SyntaxError(lex);
+
+ return init;
}
/* par.expression : '(' expression ')'
* | primitive.type array.size [ array.initializer ]
*/
private NewExpr parseNew(SymbolTable tbl) throws CompileError {
- ASTree init = null;
+ ArrayInit init = null;
int t = lex.lookAhead();
if (isBuiltinType(t)) {
lex.get();
int type = expr.getArrayType();
ASTList size = expr.getArraySize();
ASTList classname = expr.getClassName();
+ ASTree init = expr.getInitializer();
+ if (init != null)
+ init.accept(this);
+
if (size.length() > 1)
atMultiNewArray(type, classname, size);
else {
- size.head().accept(this);
+ ASTree sizeExpr = size.head();
+ if (sizeExpr != null)
+ sizeExpr.accept(this);
+
exprType = type;
arrayDim = 1;
if (type == CLASS)
}
}
+ public void atArrayInit(ArrayInit init) throws CompileError {
+ ASTList list = init;
+ while (list != null) {
+ ASTree h = list.head();
+ list = list.tail();
+ if (h != null)
+ h.accept(this);
+ }
+ }
+
protected void atMultiNewArray(int type, ASTList classname, ASTList size)
throws CompileError
{
--- /dev/null
+package javassist.compiler.ast;
+
+import javassist.compiler.CompileError;
+/**
+ * Array initializer such as <code>{ 1, 2, 3 }</code>.
+ */
+public class ArrayInit extends ASTList {
+ public ArrayInit(ASTree firstElement) {
+ super(firstElement);
+ }
+
+ public void accept(Visitor v) throws CompileError { v.atArrayInit(this); }
+
+ public String getTag() { return "array"; }
+}
arrayType = CLASS;
}
- public NewExpr(int type, ASTList arraySize, ASTree init) {
+ public NewExpr(int type, ASTList arraySize, ArrayInit init) {
super(null, new ASTList(arraySize));
newArray = true;
arrayType = type;
}
public static NewExpr makeObjectArray(ASTList className,
- ASTList arraySize, ASTree init) {
+ ASTList arraySize, ArrayInit init) {
NewExpr e = new NewExpr(className, arraySize);
e.newArray = true;
if (init != null)
public ASTList getArraySize() { return getArguments(); }
- public ASTree getInitializer() {
+ public ArrayInit getInitializer() {
ASTree t = getRight().getRight();
if (t == null)
return null;
else
- return t.getLeft();
+ return (ArrayInit)t.getLeft();
}
public void accept(Visitor v) throws CompileError { v.atNewExpr(this); }
public void atStringL(StringL n) throws CompileError {}
public void atIntConst(IntConst n) throws CompileError {}
public void atDoubleConst(DoubleConst n) throws CompileError {}
+ public void atArrayInit(ArrayInit n) throws CompileError {}
}
<br><li><a href="#alter">Altering a method body</a>
<br><li><a href="#add">Adding a new method or field</a>
<br><li><a href="#runtime">Runtime support classes</a>
+<br><li><a href="#annotation">Annotations</a>
<br><li><a href="#import">Import</a>
<br><li><a href="#limit">Limitations</a>
</ul>
<code>CtConstructor</code> can be removed by <code>removeConstructor()</code>
in <code>CtClass</code>.
+<p><br>
+
+<a name="annotation">
+<h3>4.4 Annotations</h3>
+
+<p><code>CtClass</code>, <code>CtMethod</code>, <code>CtField</code>
+and <code>CtConstructor</code> provides a convenient method
+<code>getAnnotations()</code> for reading annotations.
+It returns an annotation-type object.
+
+<p>For example, suppose the following annotation:
+
+<ul><pre>
+public @interface Author {
+ String name();
+ int year();
+}
+</pre></ul>
+
+<p>This annotation is used as the following:
+
+<ul><pre>
+@Author(name="Chiba", year=2005)
+public class Point {
+ int x, y;
+}
+</pre></ul>
+
+<p>Then, the value of the annotation can be obtained by
+<code>getAnnotations()</code>.
+It returns an array containing
+annotation-type objects.
+
+<ul><pre>
+CtClass cc = ClassPool.getDefault().get("Point");
+Object[] all = cc.getAnnotations();
+Author a = (Author)all[0];
+String name = a.name();
+int year = a.year();
+System.out.println("name: " + name + ", year: " + year);
+</pre></ul>
+
+<p>This code snippet should print:
+
+<ul><pre>
+name: Chiba, year: 2005
+</pre></ul>
+
+<p>
+Since the annoation of <code>Point</code> is only <code>@Author</code>,
+the length of the array <code>all</code> is one
+and <code>all[0]</code> is an <code>Author</code> object.
+The member values of the annotation can be obtained
+by calling <code>name()</code> and <code>year()</code>
+on the <code>Author</code> object.
+
+<p>To use <code>getAnnotations()</code>, annotation types
+such as <code>Author</code> must be included in the current
+class path. <em>They must be also accessible from a
+<code>ClassPool</code> object.</em> If the class file of an annotation
+type is not found, Javassist cannot obtain the default values
+of the members of that annotation type.
<p><br>
<a name="runtime">
-<h3>4.4 Runtime support classes</h3>
+<h3>4.5 Runtime support classes</h3>
<p>In most cases, a class modified by Javassist does not require
Javassist to run. However, some kinds of bytecode generated by the
<p><br>
<a name="import">
-<h3>4.5 Import</h3>
+<h3>4.6 Import</h3>
<p>All the class names in source code must be fully qualified
(they must include package names).
<p><br>
<a name="limit">
-<h3>4.6 Limitations</h3>
+<h3>4.7 Limitations</h3>
<p>In the current implementation, the Java compiler included in Javassist
has several limitations with respect to the language that the compiler can
<p><li>Array initializers, a comma-separated list of expressions
enclosed by braces <code>{</code> and <code>}</code>, are not
-supported.
+available unless the array dimension is one.
<p><li>Inner classes or anonymous classes are not supported.