View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.bcel.generic;
19  
20  import static org.junit.jupiter.api.Assertions.assertEquals;
21  import static org.junit.jupiter.api.Assertions.assertTrue;
22  
23  import java.io.File;
24  import java.io.IOException;
25  
26  import org.apache.bcel.AbstractTestCase;
27  import org.apache.bcel.classfile.AnnotationEntry;
28  import org.apache.bcel.classfile.ElementValuePair;
29  import org.apache.bcel.classfile.Field;
30  import org.apache.bcel.classfile.JavaClass;
31  import org.apache.bcel.util.SyntheticRepository;
32  import org.junit.jupiter.api.Test;
33  
34  public class FieldAnnotationsTestCase extends AbstractTestCase {
35      // helper methods
36      public void checkAnnotatedField(final JavaClass clazz, final String fieldname, final String AnnotationEntryName, final String AnnotationEntryElementName,
37          final String AnnotationEntryElementValue) {
38          final Field[] fields = clazz.getFields();
39          for (final Field f : fields) {
40              final AnnotationEntry[] fieldAnnotationEntrys = f.getAnnotationEntries();
41              if (f.getName().equals(fieldname)) {
42                  checkAnnotationEntry(fieldAnnotationEntrys[0], AnnotationEntryName, AnnotationEntryElementName, AnnotationEntryElementValue);
43              }
44          }
45      }
46  
47      private void checkAnnotationEntry(final AnnotationEntry a, final String name, final String elementname, final String elementvalue) {
48          assertEquals(name, a.getAnnotationType(), "Wrong AnnotationEntry name");
49          assertEquals(1, a.getElementValuePairs().length, "Wrong number of AnnotationEntry elements");
50          final ElementValuePair envp = a.getElementValuePairs()[0];
51          assertEquals(envp.getNameString(), elementname, "Wrong element name");
52          assertEquals(envp.getValue().stringifyValue(), elementvalue, "Wrong element value");
53      }
54  
55      /**
56       * Check field AnnotationEntrys are retrievable.
57       */
58      @Test
59      public void testFieldAnnotationEntrys() throws ClassNotFoundException {
60          final JavaClass clazz = getTestJavaClass(PACKAGE_BASE_NAME + ".data.AnnotatedFields");
61          // TODO L...;?
62          checkAnnotatedField(clazz, "i", "L" + PACKAGE_BASE_SIG + "/data/SimpleAnnotation;", "id", "1");
63          checkAnnotatedField(clazz, "s", "L" + PACKAGE_BASE_SIG + "/data/SimpleAnnotation;", "id", "2");
64      }
65  
66      /**
67       * Check field AnnotationEntrys (de)serialize ok.
68       */
69      @Test
70      public void testFieldAnnotationEntrysReadWrite() throws ClassNotFoundException, IOException {
71          final JavaClass clazz = getTestJavaClass(PACKAGE_BASE_NAME + ".data.AnnotatedFields");
72          checkAnnotatedField(clazz, "i", "L" + PACKAGE_BASE_SIG + "/data/SimpleAnnotation;", "id", "1");
73          checkAnnotatedField(clazz, "s", "L" + PACKAGE_BASE_SIG + "/data/SimpleAnnotation;", "id", "2");
74          // Write it out
75          final File tfile = createTestdataFile("AnnotatedFields.class");
76          clazz.dump(tfile);
77          final SyntheticRepository repos2 = createRepos(".");
78          repos2.loadClass("AnnotatedFields");
79          checkAnnotatedField(clazz, "i", "L" + PACKAGE_BASE_SIG + "/data/SimpleAnnotation;", "id", "1");
80          checkAnnotatedField(clazz, "s", "L" + PACKAGE_BASE_SIG + "/data/SimpleAnnotation;", "id", "2");
81          assertTrue(tfile.delete());
82      }
83  
84      /**
85       * Check we can load in a class, modify its field AnnotationEntrys, save it, reload it and everything is correct.
86       */
87      @Test
88      public void testFieldAnnotationModification() throws ClassNotFoundException {
89          final boolean dbg = false;
90          final JavaClass clazz = getTestJavaClass(PACKAGE_BASE_NAME + ".data.AnnotatedFields");
91          final ClassGen clg = new ClassGen(clazz);
92          Field f = clg.getFields()[0];
93          if (dbg) {
94              System.err.println("Field in freshly constructed class is: " + f);
95          }
96          if (dbg) {
97              System.err.println("AnnotationEntrys on field are: " + dumpAnnotationEntries(f.getAnnotationEntries()));
98          }
99          final AnnotationEntryGen fruitBasedAnnotationEntry = createFruitAnnotationEntry(clg.getConstantPool(), "Tomato", false);
100         final FieldGen fg = new FieldGen(f, clg.getConstantPool());
101         if (dbg) {
102             System.err.println("Adding AnnotationEntry to the field");
103         }
104         fg.addAnnotationEntry(fruitBasedAnnotationEntry);
105         if (dbg) {
106             System.err.println("FieldGen (mutable field) is " + fg);
107         }
108         if (dbg) {
109             System.err.println("with AnnotationEntrys: " + dumpAnnotationEntries(fg.getAnnotationEntries()));
110         }
111         if (dbg) {
112             System.err.println("Replacing original field with new field that has extra AnnotationEntry");
113         }
114         clg.removeField(f);
115         clg.addField(fg.getField());
116         f = clg.getFields()[1]; // there are two fields in the class, removing
117                                 // and readding has changed the order
118         // so this time index [1] is the 'int i' field
119         if (dbg) {
120             System.err.println("Field now looks like this: " + f);
121         }
122         if (dbg) {
123             System.err.println("With AnnotationEntrys: " + dumpAnnotationEntries(f.getAnnotationEntries()));
124         }
125         assertEquals(2, f.getAnnotationEntries().length, "Wrong number of AnnotationEntries");
126     }
127 }