下面列出了org.objectweb.asm.AnnotationVisitor#visitEnum ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* Makes the given visitor visit a given annotation value.
*
* @param annotationVisitor
* an annotation visitor. Maybe {@literal null}.
* @param name
* the value name.
* @param value
* the actual value.
*/
static void accept(final AnnotationVisitor annotationVisitor, final String name, final Object value) {
if (annotationVisitor != null) {
if (value instanceof String[]) {
String[] typeValue = (String[]) value;
annotationVisitor.visitEnum(name, typeValue[0], typeValue[1]);
} else if (value instanceof AnnotationNode) {
AnnotationNode annotationValue = (AnnotationNode) value;
annotationValue.accept(annotationVisitor.visitAnnotation(name, annotationValue.desc));
} else if (value instanceof List) {
AnnotationVisitor arrayAnnotationVisitor = annotationVisitor.visitArray(name);
if (arrayAnnotationVisitor != null) {
List<?> arrayValue = (List<?>) value;
for (int i = 0, n = arrayValue.size(); i < n; ++i) {
accept(arrayAnnotationVisitor, null, arrayValue.get(i));
}
arrayAnnotationVisitor.visitEnd();
}
} else {
annotationVisitor.visit(name, value);
}
}
}
public static void acceptAnnotation(final AnnotationVisitor av, final String name,
final Object value) {
if (value instanceof String[]) {
String[] typeconst = (String[]) value;
av.visitEnum(name, typeconst[0], typeconst[1]);
} else if (value instanceof AnnotationNode) {
AnnotationNode an = (AnnotationNode) value;
an.accept(av.visitAnnotation(name, an.desc));
} else if (value instanceof List<?>) {
AnnotationVisitor v = av.visitArray(name);
List<?> array = (List<?>) value;
for (int j = 0; j < array.size(); ++j) {
acceptAnnotation(v, null, array.get(j));
}
v.visitEnd();
} else {
av.visit(name, value);
}
}
/**
* Makes the given visitor visit a given annotation value.
*
* @param annotationVisitor an annotation visitor. Maybe {@literal null}.
* @param name the value name.
* @param value the actual value.
*/
static void accept(
final AnnotationVisitor annotationVisitor, final String name, final Object value) {
if (annotationVisitor != null) {
if (value instanceof String[]) {
String[] typeValue = (String[]) value;
annotationVisitor.visitEnum(name, typeValue[0], typeValue[1]);
} else if (value instanceof AnnotationNode) {
AnnotationNode annotationValue = (AnnotationNode) value;
annotationValue.accept(annotationVisitor.visitAnnotation(name, annotationValue.desc));
} else if (value instanceof List) {
AnnotationVisitor arrayAnnotationVisitor = annotationVisitor.visitArray(name);
if (arrayAnnotationVisitor != null) {
List<?> arrayValue = (List<?>) value;
for (int i = 0, n = arrayValue.size(); i < n; ++i) {
accept(arrayAnnotationVisitor, null, arrayValue.get(i));
}
arrayAnnotationVisitor.visitEnd();
}
} else {
annotationVisitor.visit(name, value);
}
}
}
/**
* Makes the given visitor visit a given annotation value.
*
* @param av
* an annotation visitor. Maybe <tt>null</tt>.
* @param name
* the value name.
* @param value
* the actual value.
*/
static void accept(final AnnotationVisitor av, final String name, final Object value) {
if (av != null) {
if (value instanceof String[]) {
String[] typeconst = (String[]) value;
av.visitEnum(name, typeconst[0], typeconst[1]);
} else if (value instanceof AnnotationNode) {
AnnotationNode an = (AnnotationNode) value;
an.accept(av.visitAnnotation(name, an.desc));
} else if (value instanceof List) {
AnnotationVisitor v = av.visitArray(name);
if (v != null) {
List<?> array = (List<?>) value;
for (int j = 0; j < array.size(); ++j) {
accept(v, null, array.get(j));
}
v.visitEnd();
}
} else {
av.visit(name, value);
}
}
}
private void visitAnnotationArrayElement(final Expression expr, final int arrayElementType, final AnnotationVisitor av) {
switch (arrayElementType) {
case 1:
AnnotationNode atAttr = (AnnotationNode) ((AnnotationConstantExpression) expr).getValue();
AnnotationVisitor av2 = av.visitAnnotation(null, BytecodeHelper.getTypeDescription(atAttr.getClassNode()));
visitAnnotationAttributes(atAttr, av2);
av2.visitEnd();
break;
case 2:
av.visit(null, ((ConstantExpression) expr).getValue());
break;
case 3:
av.visit(null, Type.getType(BytecodeHelper.getTypeDescription(expr.getType())));
break;
case 4:
PropertyExpression propExpr = (PropertyExpression) expr;
av.visitEnum(null,
BytecodeHelper.getTypeDescription(propExpr.getObjectExpression().getType()),
String.valueOf(((ConstantExpression) propExpr.getProperty()).getValue()));
break;
}
}
/**
* Makes the given visitor visit a given annotation value.
*
* @param annotationVisitor an annotation visitor. Maybe {@literal null}.
* @param name the value name.
* @param value the actual value.
*/
static void accept(
final AnnotationVisitor annotationVisitor, final String name, final Object value) {
if (annotationVisitor != null) {
if (value instanceof String[]) {
String[] typeValue = (String[]) value;
annotationVisitor.visitEnum(name, typeValue[0], typeValue[1]);
} else if (value instanceof AnnotationNode) {
AnnotationNode annotationValue = (AnnotationNode) value;
annotationValue.accept(annotationVisitor.visitAnnotation(name, annotationValue.desc));
} else if (value instanceof List) {
AnnotationVisitor arrayAnnotationVisitor = annotationVisitor.visitArray(name);
if (arrayAnnotationVisitor != null) {
List<?> arrayValue = (List<?>) value;
for (int i = 0, n = arrayValue.size(); i < n; ++i) {
accept(arrayAnnotationVisitor, null, arrayValue.get(i));
}
arrayAnnotationVisitor.visitEnd();
}
} else {
annotationVisitor.visit(name, value);
}
}
}
/**
* Makes the given visitor visit a given annotation value.
*
* @param annotationVisitor an annotation visitor. Maybe {@literal null}.
* @param name the value name.
* @param value the actual value.
*/
static void accept(
final AnnotationVisitor annotationVisitor, final String name, final Object value) {
if (annotationVisitor != null) {
if (value instanceof String[]) {
String[] typeValue = (String[]) value;
annotationVisitor.visitEnum(name, typeValue[0], typeValue[1]);
} else if (value instanceof AnnotationNode) {
AnnotationNode annotationValue = (AnnotationNode) value;
annotationValue.accept(annotationVisitor.visitAnnotation(name, annotationValue.desc));
} else if (value instanceof List) {
AnnotationVisitor arrayAnnotationVisitor = annotationVisitor.visitArray(name);
if (arrayAnnotationVisitor != null) {
List<?> arrayValue = (List<?>) value;
for (int i = 0, n = arrayValue.size(); i < n; ++i) {
accept(arrayAnnotationVisitor, null, arrayValue.get(i));
}
arrayAnnotationVisitor.visitEnd();
}
} else {
annotationVisitor.visit(name, value);
}
}
}
private static void writeGetterForMapperBy(ClassWriter classWriter, FieldNode field, String className, String getter) {
MethodVisitor methodVisitor;
AnnotationVisitor annotationVisitor0;
methodVisitor = classWriter.visitMethod(ACC_PUBLIC, getter, "()Ljava/util/Set;", "()" + getTypeSiganitureForOneToMany(field.getTypeDesc()), null);
if (DynamicEntityType.MultiReference.equals(field.getEntityType())) {
annotationVisitor0 = methodVisitor.visitAnnotation("Ljavax/persistence/ManyToMany;", true);
annotationVisitor0.visit("mappedBy", field.getMappedBy());
annotationVisitor0.visitEnd();
} else {
annotationVisitor0 = methodVisitor.visitAnnotation("Ljavax/persistence/OneToMany;", true);
annotationVisitor0.visit("mappedBy", field.getMappedBy());
if (DynamicEntityType.MultiSelection.equals(field.getEntityType())) {
annotationVisitor0.visitEnum("fetch", "Ljavax/persistence/FetchType;", "EAGER");
AnnotationVisitor annotationVisitor1 = annotationVisitor0.visitArray("cascade");
annotationVisitor1.visitEnum(null, "Ljavax/persistence/CascadeType;", CascadeType.ALL.toString());
annotationVisitor1.visitEnd();
}
annotationVisitor0.visitEnd();
}
{
annotationVisitor0 = methodVisitor.visitAnnotation("Lcom/fasterxml/jackson/annotation/JsonIgnore;", true);
annotationVisitor0.visitEnd();
}
// getter method body
methodVisitor.visitVarInsn(ALOAD, 0);
methodVisitor.visitFieldInsn(GETFIELD, className, field.getName(), "Ljava/util/Set;");
methodVisitor.visitInsn(ARETURN);
methodVisitor.visitMaxs(1, 1);
methodVisitor.visitEnd();
}
@Override
public void begin(final String nm, final Attributes attrs) {
AnnotationVisitor av = (AnnotationVisitor) peek();
if (av != null) {
av.visitEnum(attrs.getValue("name"), attrs.getValue("desc"), attrs.getValue("value"));
}
}
@Test
public void annotationDeclaration() {
ClassWriter cw = new ClassWriter(0);
cw.visit(
52,
Opcodes.ACC_PUBLIC + Opcodes.ACC_ANNOTATION + Opcodes.ACC_ABSTRACT + Opcodes.ACC_INTERFACE,
"test/Hello",
null,
"java/lang/Object",
new String[] {"java/lang/annotation/Annotation"});
AnnotationVisitor av = cw.visitAnnotation("Ljava/lang/annotation/Retention;", true);
av.visitEnum("value", "Ljava/lang/annotation/RetentionPolicy;", "RUNTIME");
av.visitEnd();
cw.visitEnd();
byte[] bytes = cw.toByteArray();
ClassFile classFile = com.google.turbine.bytecode.ClassReader.read(null, bytes);
assertThat(classFile.access())
.isEqualTo(
TurbineFlag.ACC_PUBLIC
| TurbineFlag.ACC_ANNOTATION
| TurbineFlag.ACC_ABSTRACT
| TurbineFlag.ACC_INTERFACE);
assertThat(classFile.name()).isEqualTo("test/Hello");
assertThat(classFile.signature()).isNull();
assertThat(classFile.superName()).isEqualTo("java/lang/Object");
assertThat(classFile.interfaces()).containsExactly("java/lang/annotation/Annotation");
assertThat(classFile.annotations()).hasSize(1);
ClassFile.AnnotationInfo annotation = Iterables.getOnlyElement(classFile.annotations());
assertThat(annotation.typeName()).isEqualTo("Ljava/lang/annotation/Retention;");
assertThat(annotation.elementValuePairs()).hasSize(1);
assertThat(annotation.elementValuePairs()).containsKey("value");
ElementValue value = annotation.elementValuePairs().get("value");
assertThat(value.kind()).isEqualTo(ElementValue.Kind.ENUM);
ElementValue.EnumConstValue enumValue = (ElementValue.EnumConstValue) value;
assertThat(enumValue.typeName()).isEqualTo("Ljava/lang/annotation/RetentionPolicy;");
assertThat(enumValue.constName()).isEqualTo("RUNTIME");
}
@Override
public void visitEnum(String name, String desc, String value) {
super.visitEnum(name, desc, value);
for (AnnotationVisitor dest : moreDestinations) {
dest.visitEnum(name, desc, value);
}
}
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
super.visit(version, access, name, signature, superName, interfaces);
AnnotationVisitor annotationVisitor = visitAnnotation(Type.getDescriptor(BrokenAnnotation.class), true);
annotationVisitor.visit("incompatibleValue", INTEGER);
AnnotationVisitor incompatibleValueArray = annotationVisitor.visitArray("incompatibleValueArray");
incompatibleValueArray.visit(null, INTEGER);
incompatibleValueArray.visitEnd();
if (incompatibleDeclaration) {
annotationVisitor.visitAnnotation("incompatibleAnnotationDeclaration", Type.getDescriptor(BrokenAnnotationProperty.class)).visitEnd();
AnnotationVisitor incompatibleAnnotationDeclarationArray = annotationVisitor.visitArray("incompatibleAnnotationDeclarationArray");
incompatibleAnnotationDeclarationArray.visitAnnotation(null, Type.getDescriptor(BrokenAnnotationProperty.class));
incompatibleAnnotationDeclarationArray.visitEnd();
annotationVisitor.visitEnum("incompatibleEnumerationDeclaration", Type.getDescriptor(BrokenEnumerationProperty.class), FOO.toUpperCase());
AnnotationVisitor incompatibleEnumerationDeclarationArray = annotationVisitor.visitArray("incompatibleAnnotationDeclarationArray");
incompatibleEnumerationDeclarationArray.visitEnum(null, Type.getDescriptor(BrokenEnumerationProperty.class), FOO.toUpperCase());
incompatibleEnumerationDeclarationArray.visitEnd();
}
if (allowMissingValues) {
annotationVisitor.visitEnum("unknownEnumerationConstant", Type.getDescriptor(SampleEnumeration.class), FOO);
AnnotationVisitor unknownEnumConstantArray = annotationVisitor.visitArray("unknownEnumerationConstantArray");
unknownEnumConstantArray.visitEnum(null, Type.getDescriptor(SampleEnumeration.class), FOO);
unknownEnumConstantArray.visitEnd();
annotationVisitor.visit("missingType", Type.getType("Lnet/bytebuddy/inexistant/Foo;"));
AnnotationVisitor missingTypeArray = annotationVisitor.visitArray("missingTypeArray");
missingTypeArray.visit(null, Type.getType("Lnet/bytebuddy/inexistant/Foo;"));
missingTypeArray.visitEnd();
}
annotationVisitor.visitEnd();
}
/**
* Emits the bytecode for the values of an annotation
* @param av The AnnotationVisitor to emit the bytecode to
* @param elements A collection of AnnatiotionElem that are the values of the annotation
* @param addName True, if the name of the annotation has to be added, false otherwise (should be false only in recursive calls!)
*/
protected void generateAnnotationElems(AnnotationVisitor av,
Collection<AnnotationElem> elements, boolean addName) {
if (av != null) {
Iterator<AnnotationElem> it = elements.iterator();
while (it.hasNext()) {
AnnotationElem elem = it.next();
if (elem instanceof AnnotationEnumElem) {
AnnotationEnumElem enumElem = (AnnotationEnumElem) elem;
av.visitEnum(enumElem.getName(), enumElem.getTypeName(),
enumElem.getConstantName());
} else if (elem instanceof AnnotationArrayElem) {
AnnotationArrayElem arrayElem = (AnnotationArrayElem) elem;
AnnotationVisitor arrayVisitor = av.visitArray(arrayElem
.getName());
generateAnnotationElems(arrayVisitor, arrayElem.getValues(), false);
} else if (elem instanceof AnnotationAnnotationElem) {
AnnotationAnnotationElem aElem = (AnnotationAnnotationElem) elem;
AnnotationVisitor aVisitor = av.visitAnnotation(
aElem.getName(), aElem.getValue().getType());
generateAnnotationElems(aVisitor, aElem.getValue()
.getElems(), true);
} else {
Object val = null;
if (elem instanceof AnnotationIntElem) {
AnnotationIntElem intElem = (AnnotationIntElem) elem;
int value = intElem.getValue();
switch (intElem.getKind()) {
case 'B':
val = (byte) value;
break;
case 'Z':
val = (value == 1);
break;
case 'I':
val = value;
break;
case 'S':
val = (short) value;
break;
}
} else if (elem instanceof AnnotationFloatElem) {
AnnotationFloatElem floatElem = (AnnotationFloatElem) elem;
val = floatElem.getValue();
} else if (elem instanceof AnnotationLongElem) {
AnnotationLongElem longElem = (AnnotationLongElem) elem;
val = longElem.getValue();
} else if (elem instanceof AnnotationDoubleElem) {
AnnotationDoubleElem doubleElem = (AnnotationDoubleElem) elem;
val = doubleElem.getValue();
} else if (elem instanceof AnnotationStringElem) {
AnnotationStringElem stringElem = (AnnotationStringElem) elem;
val = stringElem.getValue();
} else if (elem instanceof AnnotationClassElem) {
AnnotationClassElem classElem = (AnnotationClassElem) elem;
val = org.objectweb.asm.Type.getType(classElem
.getDesc());
}
if(addName){
av.visit(elem.getName(), val);
}
else{
av.visit(null, val);
}
}
}
av.visitEnd();
}
}
@Override
protected void generate(TraceClassVisitor cw) {
MethodVisitor mv;
AnnotationVisitor av0;
cw.visit(V1_5, ACC_PUBLIC + ACC_ANNOTATION + ACC_ABSTRACT
+ ACC_INTERFACE, "soot/asm/backend/targets/MyTestAnnotation", null,
"java/lang/Object",
new String[] { "java/lang/annotation/Annotation" });
cw.visitSource("MyTestAnnotation.java", null);
{
av0 = cw.visitAnnotation("Ljava/lang/annotation/Retention;", true);
av0.visitEnum("value", "Ljava/lang/annotation/RetentionPolicy;", "RUNTIME");
av0.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "bVal", "()B", null, null);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "dVal", "()D", null, null);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "fVal", "()F", null, null);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "iAVal", "()[I", null, null);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "iVal", "()I", null, null);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "lVal", "()J", null, null);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "rVal", "()Ljava/lang/Class;",
"()Ljava/lang/Class<Lsoot/asm/backend/targets/AnnotatedClass;>;", null);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "sAVal", "()[Ljava/lang/String;", null, null);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "sVal", "()S", null, null);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "strVal", "()Ljava/lang/String;", null, null);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "zVal", "()Z", null, null);
mv.visitEnd();
}
cw.visitEnd();
}
protected void parseAnnotation(AnnotationVisitor anno, String token) throws Exception {
if(token == null || token.length() == 0 || token.length() == 2)
return; //Nothing to parse
//System.out.println("Parse annotation: " + token);
//TODO: Handle escaped quotes properly
if(token.contains("\\\""))
throw new Exception(getCurrentTokenLine() + ": Parser currently does not handle escaped quotes in annotations! Bug me about this -_-(Unless you are on an old version");
int offset = 1; //Start after the (
int index;
while(true)
{
String valueName;
String value;
//Get value name
index = token.indexOf("=", offset);
valueName = token.substring(offset, index);
//Get value
offset = index+1;
char tokenChar = token.charAt(offset);
if(tokenChar == '"') //String value
{
index = token.indexOf('"', offset+1);
value = token.substring(offset+1, index);
anno.visit(valueName, value);
//System.out.println("AnnotationStr: " + valueName + "=" + value);
offset = index+1;
}
else if(tokenChar == '{') //Array value
throw new Exception(getCurrentTokenLine() + ": Parser currently does not handle arrays in annotations!");
else if(tokenChar == 'L') //Enum or Object Type
{
//Start with getting the Type name
index = token.indexOf(";", offset);
value = token.substring(offset, index+1);
offset = index+1;
//If we have a '.' after that, it's an Enum
if(token.charAt(offset) == '.')
{
//Find length
int index1 = token.indexOf(",", offset);
int index2 = token.indexOf(")", offset);
if(index1 < index2 && index1 != -1)
index = index1;
else
index = index2;
String entryName = token.substring(offset+1, index);
anno.visitEnum(valueName, value, entryName);
//System.out.println("AnnotationEnum: " + valueName + "=" + value + "." + entryName);
offset = index;
}
else
{
anno.visit(valueName, org.objectweb.asm.Type.getType(value));
//System.out.println("AnnotationObj: " + valueName + "=" + value);
}
} else {
//Check for Boolean and Number values
index = token.indexOf(",", offset);
if(index == -1)
value = token.substring(offset, token.length()-1);
else
value = token.substring(offset, index);
ValueType parsedValue = parseValue(value);
anno.visit(valueName, parsedValue.value);
//System.out.println("AnnotationBoolNr: " + valueName + "=" + parsedValue.value);
offset = index;
}
tokenChar = token.charAt(offset);
if(tokenChar == ',') //Continue to next value
{
offset ++;
continue;
}
else if(tokenChar == ')') //Done
break;
throw new Exception(getCurrentTokenLine() + ": Error while parsing Annotation: Expected ',' or ')', got: " + tokenChar);
}
//TODO: If we get "// invisible" before end of line, the annotation is invisible?
}