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  
19  package org.apache.bcel.generic;
20  
21  import java.io.File;
22  import java.io.IOException;
23  
24  import org.apache.bcel.AbstractTestCase;
25  import org.apache.bcel.classfile.AnnotationEntry;
26  import org.apache.bcel.classfile.ElementValuePair;
27  import org.apache.bcel.classfile.Field;
28  import org.apache.bcel.classfile.JavaClass;
29  import org.apache.bcel.util.SyntheticRepository;
30  
31  public class FieldAnnotationsTestCase extends AbstractTestCase
32  {
33      /**
34       * Check field AnnotationEntrys are retrievable.
35       */
36      public void testFieldAnnotationEntrys() throws ClassNotFoundException
37      {
38          final JavaClass clazz = getTestClass(PACKAGE_BASE_NAME+".data.AnnotatedFields");
39          // TODO L...;?
40          checkAnnotatedField(clazz, "i", "L"+PACKAGE_BASE_SIG+"/data/SimpleAnnotation;", "id", "1");
41          checkAnnotatedField(clazz, "s", "L"+PACKAGE_BASE_SIG+"/data/SimpleAnnotation;", "id", "2");
42      }
43  
44      /**
45       * Check field AnnotationEntrys (de)serialize ok.
46       */
47      public void testFieldAnnotationEntrysReadWrite() throws ClassNotFoundException,
48              IOException
49      {
50          final JavaClass clazz = getTestClass(PACKAGE_BASE_NAME+".data.AnnotatedFields");
51          checkAnnotatedField(clazz, "i", "L"+PACKAGE_BASE_SIG+"/data/SimpleAnnotation;", "id", "1");
52          checkAnnotatedField(clazz, "s", "L"+PACKAGE_BASE_SIG+"/data/SimpleAnnotation;", "id", "2");
53          // Write it out
54          final File tfile = createTestdataFile("AnnotatedFields.class");
55          clazz.dump(tfile);
56          final SyntheticRepository repos2 = createRepos(".");
57          repos2.loadClass("AnnotatedFields");
58          checkAnnotatedField(clazz, "i", "L"+PACKAGE_BASE_SIG+"/data/SimpleAnnotation;", "id", "1");
59          checkAnnotatedField(clazz, "s", "L"+PACKAGE_BASE_SIG+"/data/SimpleAnnotation;", "id", "2");
60          assertTrue(tfile.delete());
61      }
62  
63      /**
64       * Check we can load in a class, modify its field AnnotationEntrys, save it,
65       * reload it and everything is correct.
66       */
67      public void testFieldAnnotationModification()
68              throws ClassNotFoundException
69      {
70          final boolean dbg = false;
71          final JavaClass clazz = getTestClass(PACKAGE_BASE_NAME+".data.AnnotatedFields");
72          final ClassGen clg = new ClassGen(clazz);
73          Field f = clg.getFields()[0];
74          if (dbg) {
75              System.err.println("Field in freshly constructed class is: " + f);
76          }
77          if (dbg) {
78              System.err.println("AnnotationEntrys on field are: "
79                      + dumpAnnotationEntries(f.getAnnotationEntries()));
80          }
81          final AnnotationEntryGen fruitBasedAnnotationEntry = createFruitAnnotationEntry(clg
82                  .getConstantPool(), "Tomato", false);
83          final FieldGen fg = new FieldGen(f, clg.getConstantPool());
84          if (dbg) {
85              System.err.println("Adding AnnotationEntry to the field");
86          }
87          fg.addAnnotationEntry(fruitBasedAnnotationEntry);
88          if (dbg) {
89              System.err.println("FieldGen (mutable field) is " + fg);
90          }
91          if (dbg) {
92              System.err.println("with AnnotationEntrys: "
93                      + dumpAnnotationEntries(fg.getAnnotationEntries()));
94          }
95          if (dbg) {
96              System.err
97                      .println("Replacing original field with new field that has extra AnnotationEntry");
98          }
99          clg.removeField(f);
100         clg.addField(fg.getField());
101         f = clg.getFields()[1]; // there are two fields in the class, removing
102                                 // and readding has changed the order
103         // so this time index [1] is the 'int i' field
104         if (dbg) {
105             System.err.println("Field now looks like this: " + f);
106         }
107         if (dbg) {
108             System.err.println("With AnnotationEntrys: "
109                     + dumpAnnotationEntries(f.getAnnotationEntries()));
110         }
111         assertTrue("Should be 2 AnnotationEntrys on this field, but there are "
112                 + f.getAnnotationEntries().length, f.getAnnotationEntries().length == 2);
113     }
114 
115     // helper methods
116     public void checkAnnotatedField(final JavaClass clazz, final String fieldname,
117             final String AnnotationEntryName, final String AnnotationEntryElementName,
118             final String AnnotationEntryElementValue)
119     {
120         final Field[] fields = clazz.getFields();
121         for (final Field f : fields) {
122             final AnnotationEntry[] fieldAnnotationEntrys = f.getAnnotationEntries();
123             if (f.getName().equals(fieldname))
124             {
125                 checkAnnotationEntry(fieldAnnotationEntrys[0], AnnotationEntryName,
126                         AnnotationEntryElementName, AnnotationEntryElementValue);
127             }
128         }
129     }
130 
131     private void checkAnnotationEntry(final AnnotationEntry a, final String name, final String elementname,
132             final String elementvalue)
133     {
134         assertTrue("Expected AnnotationEntry to have name " + name
135                 + " but it had name " + a.getAnnotationType(), a.getAnnotationType()
136                 .equals(name));
137         assertTrue("Expected AnnotationEntry to have one element but it had "
138                 + a.getElementValuePairs().length, a.getElementValuePairs().length == 1);
139         final ElementValuePair envp = a.getElementValuePairs()[0];
140         assertTrue("Expected element name " + elementname + " but was "
141                 + envp.getNameString(), elementname
142                 .equals(envp.getNameString()));
143         assertTrue("Expected element value " + elementvalue + " but was "
144                 + envp.getValue().stringifyValue(), elementvalue.equals(envp
145                 .getValue().stringifyValue()));
146     }
147 
148     // helper methods
149     public void checkValue(final AnnotationEntry a, final String name, final String tostring)
150     {
151         for (int i = 0; i < a.getElementValuePairs().length; i++)
152         {
153             final ElementValuePair element = a.getElementValuePairs()[i];
154             if (element.getNameString().equals(name))
155             {
156                 if (!element.getValue().stringifyValue().equals(tostring))
157                 {
158                     fail("Expected element " + name + " to have value "
159                             + tostring + " but it had value "
160                             + element.getValue().stringifyValue());
161                 }
162                 return;
163             }
164         }
165         fail("Didnt find named element " + name);
166     }
167 }