package org.jboss.capedwarf.bytecode; import java.util.Collection; import java.util.LinkedList; import java.util.List; import javassist.CtClass; import javassist.CtMethod; import javassist.NotFoundException; import javassist.bytecode.AnnotationsAttribute; import javassist.bytecode.ClassFile; import javassist.bytecode.ConstPool; import javassist.bytecode.MethodInfo; import javassist.bytecode.annotation.Annotation; import javassist.bytecode.annotation.ArrayMemberValue; import javassist.bytecode.annotation.ClassMemberValue; import javassist.bytecode.annotation.EnumMemberValue; import javassist.bytecode.annotation.MemberValue; import javassist.bytecode.annotation.StringMemberValue; /** * */ public abstract class Annotator { private CtClass clazz; private ClassFile classFile; private ConstPool constPool; public Annotator(CtClass clazz) { this.clazz = clazz; classFile = clazz.getClassFile(); constPool = classFile.getConstPool(); } protected CtClass getClazz() { return clazz; } protected ClassFile getClassFile() { return classFile; } protected ConstPool getConstPool() { return constPool; } protected ClassLoader getClassLoader() { return clazz.getClassPool().getClassLoader(); } public abstract void addAnnotations() throws Exception; protected EnumMemberValue createEnumMemberValue(Enum enumValue) { int enumClassIndex = constPool.addUtf8Info(enumValue.getDeclaringClass().getName()); int enumValueIndex = constPool.addUtf8Info(enumValue.name()); return new EnumMemberValue(enumClassIndex, enumValueIndex, constPool); } protected ClassMemberValue createClassMemberValue(Class<?> clazz) { return createClassMemberValue(clazz.getName()); } protected ClassMemberValue createClassMemberValue(String clazz) { return new ClassMemberValue(clazz, constPool); } @SuppressWarnings("unchecked") protected void addAnnotationsToClass(Class<? extends java.lang.annotation.Annotation>... annotationClasses) { addAnnotationsToClass(createAnnotations(annotationClasses)); } protected void addAnnotationsToClass(Annotation... annotations) { AnnotationsAttribute aa = (AnnotationsAttribute) classFile.getAttribute(AnnotationsAttribute.visibleTag); if (aa == null) { classFile.addAttribute(createAnnotationAttribute(annotations)); } else { addAnnotations(aa, annotations); } } protected void addAnnotationsToMethod(String methodName, Annotation... annotations) throws NotFoundException { addAnnotationsToMethod(clazz.getDeclaredMethod(methodName), annotations); } protected void addAnnotationsToMethod(CtMethod method, Collection<Annotation> annotations) { addAnnotationsToMethod(method, annotations.toArray(new Annotation[annotations.size()])); } protected void addAnnotationsToMethod(CtMethod method, Annotation... annotations) { MethodInfo methodInfo = method.getMethodInfo(); AnnotationsAttribute aa = (AnnotationsAttribute) methodInfo.getAttribute(AnnotationsAttribute.visibleTag); if (aa == null) { methodInfo.addAttribute(createAnnotationAttribute(annotations)); } else { addAnnotations(aa, annotations); } } protected void addAnnotationsToField(String fieldName, Annotation... annotations) throws NotFoundException { clazz.getDeclaredField(fieldName).getFieldInfo().addAttribute(createAnnotationAttribute(annotations)); } private Annotation[] createAnnotations(Class<? extends java.lang.annotation.Annotation>[] annotationClasses) { List<Annotation> annotationList = new LinkedList<Annotation>(); for (Class<? extends java.lang.annotation.Annotation> annotationClass : annotationClasses) { annotationList.add(createAnnotation(annotationClass)); } return annotationList.toArray(new Annotation[annotationList.size()]); } protected Annotation createAnnotation(Class<? extends java.lang.annotation.Annotation> annotationClass) { return new Annotation(annotationClass.getName(), constPool); } protected Annotation createAnnotation(Class<? extends java.lang.annotation.Annotation> annotationClass, MemberValue value) { return createAnnotation(annotationClass, "value", value); } protected Annotation createAnnotation(Class<? extends java.lang.annotation.Annotation> annotationClass, String name, MemberValue value) { Annotation queryParam = createAnnotation(annotationClass); queryParam.addMemberValue(name, value); return queryParam; } private AnnotationsAttribute createAnnotationAttribute(Annotation... annotations) { AnnotationsAttribute attribute = new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag); addAnnotations(attribute, annotations); return attribute; } private void addAnnotations(AnnotationsAttribute attribute, Annotation[] annotations) { for (Annotation annotation : annotations) { attribute.addAnnotation(annotation); } } protected StringMemberValue memberValueOf(String value) { return new StringMemberValue(value, getConstPool()); } protected ArrayMemberValue createSingleElementArrayMemberValue(Class<?> arrayType, MemberValue element) { ArrayMemberValue array = new ArrayMemberValue(createClassMemberValue(arrayType), getConstPool()); array.setValue(new MemberValue[]{element}); return array; } }