Hello bcel developers,
I’m sorry in advance if I’m writing to a wrong place.
I use bcel to annotate some specific fields and methods in already compiled
code. Currently I work on task to migrate from version 6.0 to 6.2. I run into
some issues and seek for advice:
1. org.apache.bcel.util.BCELifier does not support runtime annotations
for class fields and methods (I did not test class annotations). Should it
support them? When debugging I found that i.e. field object in method
org.apache.bcel.util.BCELifier#visitField does contain attribute of type
org.apache.bcel.classfile.RuntimeVisibleAnnotations and its table is filled
appropriately. It seems org.apache.bcel.util.BCELifier#visitField is missing
some code for annotation support. Basically same thing applies to
org.apache.bcel.util.BCELifier#visitMethod as well.
2. org.apache.bcel.generic.FieldGenOrMethodGen#addAnnotationEntry method
is now protected. Should it be deprecated? Seems now correct way to read/write
annotations is to use org.apache.bcel.classfile.RuntimeVisibleAnnotations
attribute.
3. While trying to implement code that adds runtime annotation to a field
I noticed that org.apache.bcel.classfile.RuntimeVisibleAnnotations has a
constructor only for reading from input. Should it have one for creating the
attribute? I.e. it could provide the second constructor from its superclass:
org.apache.bcel.classfile.Annotations#Annotations(byte, int, int,
org.apache.bcel.classfile.AnnotationEntry[],
org.apache.bcel.classfile.ConstantPool, boolean) to avoid unnecessary
complicated implementation on user end. I temporarily solved it by copying
org.apache.bcel.classfile.RuntimeVisibleAnnotations class to my source base and
providing the appropriate constructor. Also when creating
org.apache.bcel.classfile.AnnotationEntry I run into NullPointerException. None
of its constructors initialize
org.apache.bcel.classfile.AnnotationEntry#element_value_pairs collection, only
method org.apache.bcel.classfile.AnnotationEntry#read does. This issue I had to
solve via reflection. Should it initialize the collection? Maybe it could be
initialized on demand if not already. Here’s a simple fragment of code that
adds runtime annotation to a field for the version 6.2:
private static void addTestAnnotation(FieldGen field)
{
ConstantPoolGen cp = field.getConstantPool();
ObjectType objectType = new
ObjectType("com.nomagic.tools.ant.annotator.TestAnnotation");
AnnotationEntry annotationEntry = new
AnnotationEntry(cp.addUtf8(objectType.getSignature()), cp.getConstantPool(),
true);
fixUninitializedLists(annotationEntry);
SimpleElementValueGen value = new
SimpleElementValueGen(ElementValueGen.STRING, cp, "Some test text");
ElementValuePairGen pairGen = new ElementValuePairGen("testMessage", value,
cp);
annotationEntry.addElementNameValuePair(pairGen.getElementNameValuePair());
AnnotationEntry[] annotation_table = new AnnotationEntry[]{annotationEntry};
int nameIndex =
cp.addUtf8(Const.getAttributeName(Const.ATTR_RUNTIME_INVISIBLE_ANNOTATIONS));
// RuntimeVisibleAnnotations is copy of original class with changed
constructor
RuntimeVisibleAnnotations runtimeVisibleAnnotations = new
RuntimeVisibleAnnotations(nameIndex, annotation_table.length, annotation_table,
cp.getConstantPool());
field.addAttribute(runtimeVisibleAnnotations);
}
private static void fixUninitializedLists(AnnotationEntry annotationEntry)
{
java.lang.reflect.Field[] fields =
annotationEntry.getClass().getDeclaredFields();
for (java.lang.reflect.Field field : fields)
{
field.setAccessible(true);
if(field.getType().equals(List.class))
{
try
{
Object value = field.get(annotationEntry);
if (value == null)
{
field.set(annotationEntry, new ArrayList());
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
}
Maybe org.apache.bcel.generic.FieldGenOrMethodGen class could have a method
like addRuntimeVisibleAnnotation(AnnotationEntryGen) and inside it could check
if it has special annotations attribute (create if not) and then add annotation
to the attribute.
Seems like adding annotation to a class field or method is no longer supported.
Or maybe implementation is not complete. Or maybe I’m using wrong API.
If you need, I can provide sample intellij project.
Please let me know what you think about this.
Sincerely,
--
Tomas Lukosius
Software Developer
No Magic Europe
Savanoriu ave. 363, LT-51480, Kaunas, Lithuania
Phone: +370 37 324032, fax: +370 37 320670
E-mail: [email protected]<mailto:[email protected]>
www.nomagic.com<http://www.nomagic.com/>
www.magicdraw.com<http://www.magicdraw.com/>
Important change to No Magic e-mail addresses. Following No Magic acquisition
by Dassault Systèmes, please use my Dassault Systèmes email address
[email protected]<mailto:[email protected]> to contact me. Don't
forget to add the new address to your Safe Senders list, to ensure you will
continue to receive my e-mails.