--- /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;
+
+import javassist.CtClass;
+import javassist.bytecode.annotation.AnnotationsWriter;
+import javassist.bytecode.annotation.MemberValue;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * A class representing <code>AnnotationDefault_attribute</code>.
+ *
+ * <p>For example, if you declare the following annotation type:
+ *
+ * <ul><pre>
+ * @interface Author {
+ * String name() default "Shakespeare";
+ * int age() default 99;
+ * }
+ * </pre></ul>
+ *
+ * <p>The defautl values of <code>name</code> and <code>age</code>
+ * are stored as annotation default attributes in <code>Author.class</code>.
+ * The following code snippet obtains the default value of <code>name</code>:
+ *
+ * <ul><pre>
+ * ClassPool pool = ...
+ * CtClass cc = pool.get("Author");
+ * CtMethod cm = cc.getDeclaredMethod("age");
+ * MethodInfo minfo = cm.getMethodInfo();
+ * AnnotationDefaultAttribute ada
+ * = (AnnotationDefaultAttribute)
+ * minfo.getAttribute(AnnotationDefaultAttribute.tag);
+ * MemberValue value = ada.getDefaultValue()); // default value of age
+ * </pre></ul>
+ *
+ * <p>If the following statement is executed after the code above,
+ * the default value of age is set to 80:
+ *
+ * <ul><pre>
+ * ada.setDefaultValue(new IntegerMemberValue(minfo.getConstPool(), 80));
+ * </pre></ul>
+ *
+ * @see AnnotationsAttribute
+ * @see javassist.bytecode.annotation.MemberValue
+ */
+
+public class AnnotationDefaultAttribute extends AttributeInfo {
+ /**
+ * The name of the <code>AnnotationDefault</code> attribute.
+ */
+ public static final String tag = "AnnotationDefault";
+
+ /**
+ * Constructs an <code>AnnotationDefault_attribute</code>.
+ *
+ * @param cp constant pool
+ * @param info the contents of this attribute. It does not
+ * include <code>attribute_name_index</code> or
+ * <code>attribute_length</code>.
+ */
+ public AnnotationDefaultAttribute(ConstPool cp, byte[] info) {
+ super(cp, tag, info);
+ }
+
+ /**
+ * Constructs an empty <code>AnnotationDefault_attribute</code>.
+ * The default value can be set by <code>setDefaultValue()</code>.
+ *
+ * @param cp constant pool
+ * @see #setDefaultValue(javassist.bytecode.annotation.MemberValue)
+ */
+ public AnnotationDefaultAttribute(ConstPool cp) {
+ this(cp, new byte[] { 0, 0 });
+ }
+
+ /**
+ * @param n the attribute name.
+ */
+ AnnotationDefaultAttribute(ConstPool cp, int n, DataInputStream in)
+ throws IOException
+ {
+ super(cp, n, in);
+ }
+
+ /**
+ * Copies this attribute and returns a new copy.
+ */
+ public AttributeInfo copy(ConstPool newCp, Map classnames) {
+ AnnotationsAttribute.Copier copier
+ = new AnnotationsAttribute.Copier(info, constPool, newCp, classnames);
+ try {
+ copier.memberValue(0);
+ return new AnnotationDefaultAttribute(newCp, copier.close());
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+
+ /**
+ * Obtains the default value represented by this attribute.
+ */
+ public MemberValue getDefaultValue()
+ {
+ try {
+ return new AnnotationsAttribute.Parser(info, constPool)
+ .parseMemberValue();
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+
+ /**
+ * Changes the default value represented by this attribute.
+ *
+ * @param value the new value.
+ * @see javassist.bytecode.annotation.Annotation#createMemberValue(ConstPool, CtClass)
+ */
+ public void setDefaultValue(MemberValue value) {
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ AnnotationsWriter writer = new AnnotationsWriter(output, constPool);
+ try {
+ value.write(writer);
+ writer.close();
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e); // should never reach here.
+ }
+
+ set(output.toByteArray());
+
+ }
+
+ /**
+ * Returns a string representation of this object.
+ */
+ public String toString() {
+ return getDefaultValue().toString();
+ }
+}
* <p>For example,
*
* <ul><pre>
+ * import javassist.bytecode.annotation.Annotation;
+ * :
* CtMethod m = ... ;
* MethodInfo minfo = m.getMethodInfo();
* AnnotationsAttribute attr = (AnnotationsAttribute)
- * minfo.getAttribute(AnnotationsAttribute.visibleTag);
+ * minfo.getAttribute(AnnotationsAttribute.invisibleTag);
* Annotation an = attr.getAnnotation("Author");
- * String s = ((StringMemberValue)a.getMemberValue("name")).getValue();
+ * String s = ((StringMemberValue)an.getMemberValue("name")).getValue();
* System.out.println("@Author(name=" + s + ")");
* </pre></ul>
*
* from the <code>MethodInfo</code> object specified by <code>minfo</code>.
* Then, it prints the value of <code>name</code> in <code>Author</code>.
*
+ * <p>If the annotation type <code>Author</code> is annotated by a meta annotation:
+ *
+ * <ul><pre>
+ * @Retention(RetentionPolicy.RUNTIME)
+ * </pre></ul>
+ *
+ * <p>Then <code>Author</code> is visible at runtime. Therefore, the third
+ * statement of the code snippet above must be changed into:
+ *
+ * <ul><pre>
+ * AnnotationsAttribute attr = (AnnotationsAttribute)
+ * minfo.getAttribute(AnnotationsAttribute.visibleTag);
+ * </pre></ul>
+ *
+ * <p>The attribute tag must be <code>visibleTag</code> instead of
+ * <code>invisibleTag</code>.
+ *
+ * <p>If the member value of an annotation is not specified, the default value
+ * is used as that member value. If so, <code>getMemberValue()</code> in
+ * <code>Annotation</code> returns <code>null</code>
+ * since the default value is not included in the
+ * <code>AnnotationsAttribute</code>. It is included in the
+ * <code>AnnotationDefaultAttribute</code> of the method declared in the
+ * annotation type.
+ *
* <p>If you want to record a new AnnotationAttribute object, execute the
* following snippet:
*
* cf.addAttribute(attr);
* </pre></ul>
*
+ * @see AnnotationDefaultAttribute
* @see javassist.bytecode.annotation.Annotation
*/
public class AnnotationsAttribute extends AttributeInfo {
Annotation[][] allParams; // all parameters
Annotation[] allAnno; // all annotations
Annotation currentAnno; // current annotation
- MemberValue memberValue;
+ MemberValue currentMember; // current member
/**
* Constructs a parser. This parser constructs a parse tree of
return allAnno;
}
+ MemberValue parseMemberValue() throws Exception {
+ memberValue(0);
+ return currentMember;
+ }
+
void parameters(int numParam, int pos) throws Exception {
Annotation[][] params = new Annotation[numParam][];
for (int i = 0; i < numParam; ++i) {
int memberValuePair(int pos, int nameIndex) throws Exception {
pos = super.memberValuePair(pos, nameIndex);
- currentAnno.addMemberValue(nameIndex, memberValue);
+ currentAnno.addMemberValue(nameIndex, currentMember);
return pos;
}
throw new RuntimeException("unknown tag:" + tag);
}
- memberValue = m;
+ currentMember = m;
super.constValueMember(tag, index);
}
void enumMemberValue(int typeNameIndex, int constNameIndex)
throws Exception
{
- memberValue = new EnumMemberValue(typeNameIndex,
+ currentMember = new EnumMemberValue(typeNameIndex,
constNameIndex, pool);
super.enumMemberValue(typeNameIndex, constNameIndex);
}
void classMemberValue(int index) throws Exception {
- memberValue = new ClassMemberValue(index, pool);
+ currentMember = new ClassMemberValue(index, pool);
super.classMemberValue(index);
}
int annotationMemberValue(int pos) throws Exception {
Annotation anno = currentAnno;
pos = super.annotationMemberValue(pos);
- memberValue = new AnnotationMemberValue(currentAnno, pool);
+ currentMember = new AnnotationMemberValue(currentAnno, pool);
currentAnno = anno;
return pos;
}
MemberValue[] elements = new MemberValue[num];
for (int i = 0; i < num; ++i) {
pos = memberValue(pos);
- elements[i] = memberValue;
+ elements[i] = currentMember;
}
amv.setValue(elements);
- memberValue = amv;
+ currentMember = amv;
return pos;
}
}
int name = in.readUnsignedShort();
String nameStr = cp.getUtf8Info(name);
if (nameStr.charAt(0) < 'L') {
- if (nameStr.equals(CodeAttribute.tag))
+ if (nameStr.equals(AnnotationDefaultAttribute.tag))
+ return new AnnotationDefaultAttribute(cp, name, in);
+ else if (nameStr.equals(CodeAttribute.tag))
return new CodeAttribute(cp, name, in);
else if (nameStr.equals(ConstantAttribute.tag))
return new ConstantAttribute(cp, name, in);
}
}
- private MemberValue createMemberValue(ConstPool cp, CtClass returnType)
+ /**
+ * Makes an instance of <code>MemberValue</code>.
+ *
+ * @param cp the constant pool table.
+ * @param type the type of the member.
+ */
+ public static MemberValue createMemberValue(ConstPool cp, CtClass type)
throws javassist.NotFoundException
{
- if (returnType == CtClass.booleanType)
+ if (type == CtClass.booleanType)
return new BooleanMemberValue(cp);
- else if (returnType == CtClass.byteType)
+ else if (type == CtClass.byteType)
return new ByteMemberValue(cp);
- else if (returnType == CtClass.charType)
+ else if (type == CtClass.charType)
return new CharMemberValue(cp);
- else if (returnType == CtClass.shortType)
+ else if (type == CtClass.shortType)
return new ShortMemberValue(cp);
- else if (returnType == CtClass.intType)
+ else if (type == CtClass.intType)
return new IntegerMemberValue(cp);
- else if (returnType == CtClass.longType)
+ else if (type == CtClass.longType)
return new LongMemberValue(cp);
- else if (returnType == CtClass.floatType)
+ else if (type == CtClass.floatType)
return new FloatMemberValue(cp);
- else if (returnType == CtClass.doubleType)
+ else if (type == CtClass.doubleType)
return new DoubleMemberValue(cp);
- else if (returnType.getName().equals("java.lang.Class"))
+ else if (type.getName().equals("java.lang.Class"))
return new ClassMemberValue(cp);
- else if (returnType.getName().equals("java.lang.String"))
+ else if (type.getName().equals("java.lang.String"))
return new StringMemberValue(cp);
- else if (returnType.isArray()) {
- CtClass arrayType = returnType.getComponentType();
- MemberValue type = createMemberValue(cp, arrayType);
- return new ArrayMemberValue(type, cp);
+ else if (type.isArray()) {
+ CtClass arrayType = type.getComponentType();
+ MemberValue member = createMemberValue(cp, arrayType);
+ return new ArrayMemberValue(member, cp);
}
- else if (returnType.isInterface()) {
- Annotation info = new Annotation(cp, returnType);
+ else if (type.isInterface()) {
+ Annotation info = new Annotation(cp, type);
return new AnnotationMemberValue(info, cp);
}
else {
// but JBoss has an Annotation Compiler for JDK 1.4
// and I want it to work with that. - Bill Burke
EnumMemberValue emv = new EnumMemberValue(cp);
- emv.setType(returnType.getName());
+ emv.setType(type.getName());
return emv;
}
}
return value.toString();
}
- void write(AnnotationsWriter writer) throws IOException {
+ /**
+ * Writes the value.
+ */
+ public void write(AnnotationsWriter writer) throws IOException {
writer.annotationValue();
value.write(writer);
}
return buf.toString();
}
- void write(AnnotationsWriter writer) throws IOException {
+ /**
+ * Writes the value.
+ */
+ public void write(AnnotationsWriter writer) throws IOException {
int num = values.length;
writer.arrayValue(num);
for (int i = 0; i < num; ++i)
return getValue() ? "true" : "false";
}
- void write(AnnotationsWriter writer) throws IOException {
+ /**
+ * Writes the value.
+ */
+ public void write(AnnotationsWriter writer) throws IOException {
writer.constValueIndex(getValue());
}
return Byte.toString(getValue());
}
- void write(AnnotationsWriter writer) throws IOException {
+ /**
+ * Writes the value.
+ */
+ public void write(AnnotationsWriter writer) throws IOException {
writer.constValueIndex(getValue());
}
return Character.toString(getValue());
}
- void write(AnnotationsWriter writer) throws IOException {
+ /**
+ * Writes the value.
+ */
+ public void write(AnnotationsWriter writer) throws IOException {
writer.constValueIndex(getValue());
}
return "<" + getValue() + " class>";
}
- void write(AnnotationsWriter writer) throws IOException {
+ /**
+ * Writes the value.
+ */
+ public void write(AnnotationsWriter writer) throws IOException {
writer.classInfoIndex(valueIndex);
}
*
* @author <a href="mailto:bill@jboss.org">Bill Burke</a>
* @author Shigeru Chiba
- * @version $Revision: 1.4 $
+ * @version $Revision: 1.5 $
*/
public class DoubleMemberValue extends MemberValue {
int valueIndex;
return Double.toString(getValue());
}
- void write(AnnotationsWriter writer) throws IOException {
+ /**
+ * Writes the value.
+ */
+ public void write(AnnotationsWriter writer) throws IOException {
writer.constValueIndex(getValue());
}
return getType() + "." + getValue();
}
- void write(AnnotationsWriter writer) throws IOException {
+ /**
+ * Writes the value.
+ */
+ public void write(AnnotationsWriter writer) throws IOException {
writer.enumConstValue(getType(), getValue());
}
*
* @author <a href="mailto:bill@jboss.org">Bill Burke</a>
* @author Shigeru Chiba
- * @version $Revision: 1.4 $
+ * @version $Revision: 1.5 $
*/
public class FloatMemberValue extends MemberValue {
int valueIndex;
return Float.toString(getValue());
}
- void write(AnnotationsWriter writer) throws IOException {
+ /**
+ * Writes the value.
+ */
+ public void write(AnnotationsWriter writer) throws IOException {
writer.constValueIndex(getValue());
}
return Integer.toString(getValue());
}
- void write(AnnotationsWriter writer) throws IOException {
+ /**
+ * Writes the value.
+ */
+ public void write(AnnotationsWriter writer) throws IOException {
writer.constValueIndex(getValue());
}
return Long.toString(getValue());
}
- void write(AnnotationsWriter writer) throws IOException {
+ /**
+ * Writes the value.
+ */
+ public void write(AnnotationsWriter writer) throws IOException {
writer.constValueIndex(getValue());
}
*/
public abstract void accept(MemberValueVisitor visitor);
- abstract void write(AnnotationsWriter w) throws IOException;
+ /**
+ * Writes the value.
+ */
+ public abstract void write(AnnotationsWriter w) throws IOException;
}
return Short.toString(getValue());
}
- void write(AnnotationsWriter writer) throws IOException {
+ /**
+ * Writes the value.
+ */
+ public void write(AnnotationsWriter writer) throws IOException {
writer.constValueIndex(getValue());
}
return "\"" + getValue() + "\"";
}
- void write(AnnotationsWriter writer) throws IOException {
+ /**
+ * Writes the value.
+ */
+ public void write(AnnotationsWriter writer) throws IOException {
writer.constValueIndex(getValue());
}