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: tomas.lukos...@nomagic.com<mailto:tomas.lukos...@nomagic.com>
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 
tomas.lukos...@3ds.com<mailto:tomas.lukos...@3ds.com> 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.

Reply via email to