8acef375735e652413db5673fc875fe4839e4635
[jpf-core.git] / src / main / gov / nasa / jpf / jvm / JVMAnnotationParser.java
1 /*
2  * Copyright (C) 2014, United States Government, as represented by the
3  * Administrator of the National Aeronautics and Space Administration.
4  * All rights reserved.
5  *
6  * The Java Pathfinder core (jpf-core) platform is licensed under the
7  * Apache License, Version 2.0 (the "License"); you may not use this file except
8  * in compliance with the License. You may obtain a copy of the License at
9  * 
10  *        http://www.apache.org/licenses/LICENSE-2.0. 
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and 
16  * limitations under the License.
17  */
18 package gov.nasa.jpf.jvm;
19
20 import gov.nasa.jpf.JPFException;
21 import gov.nasa.jpf.vm.AnnotationInfo;
22 import gov.nasa.jpf.vm.AnnotationParser;
23 import gov.nasa.jpf.vm.ClassParseException;
24 import gov.nasa.jpf.vm.Types;
25
26 /**
27  * parser that reads annotation classfiles and extracts default value entries
28  * 
29  * Java annotations form a different type system. Java annotations are essentially
30  * restricted interfaces (no super-interface, no fields other than static finals
31  * that are inlined by the compiler)
32  * 
33  * Since Java annotations use only a small subset of the Java classfile format
34  * we only have to parse methods and method attributes
35  * 
36  * <2do> class and enum values are not yet supported
37  */
38 public class JVMAnnotationParser extends ClassFileReaderAdapter implements AnnotationParser {
39
40   ClassFile cf;
41   AnnotationInfo ai;
42   
43   String key;
44   Object value;
45   Object[] valElements;
46
47   String annotationName;
48   AnnotationInfo.Entry[] entries;
49   
50   public JVMAnnotationParser (ClassFile cf) {
51     this.cf = cf;
52   }
53
54   @Override
55   public void parse (AnnotationInfo ai) throws ClassParseException {
56     this.ai = ai;
57     
58     cf.parse(this);
59   }
60     
61   //--- the overridden ClassFileReader methods
62
63   @Override
64   public void setClass (ClassFile cf, String clsName, String superClsName, int flags, int cpCount) throws ClassParseException {
65     entries = null;
66     annotationName = Types.getClassNameFromTypeName(clsName);
67     
68     ai.setName(annotationName);
69   }
70
71   @Override
72   public void setInterface (ClassFile cf, int ifcIndex, String ifcName) {
73     if (!"java/lang/annotation/Annotation".equals(ifcName)) {
74       throw new JPFException("illegal annotation interface of: " + annotationName + " is " + ifcName);
75     }
76   }
77
78   @Override
79   public void setMethodCount (ClassFile cf, int methodCount) {
80     entries = new AnnotationInfo.Entry[methodCount];
81   }
82
83   @Override
84   public void setMethod (ClassFile cf, int methodIndex, int accessFlags, String name, String descriptor) {
85     key = name;
86     value = null;
87   }
88
89   @Override
90   public void setMethodDone (ClassFile cf, int methodIndex){
91     entries[methodIndex] = new AnnotationInfo.Entry(key, value);
92   }
93   
94   @Override
95   public void setMethodsDone (ClassFile cf){
96     ai.setEntries(entries);
97   }
98   
99   @Override
100   public void setMethodAttribute (ClassFile cf, int methodIndex, int attrIndex, String name, int attrLength) {
101     if (name == ClassFile.ANNOTATIONDEFAULT_ATTR) {
102       cf.parseAnnotationDefaultAttr(this, key);
103     }
104   }
105
106   @Override
107   public void setClassAttribute (ClassFile cf, int attrIndex, String name, int attrLength) {
108     if (name == ClassFile.RUNTIME_VISIBLE_ANNOTATIONS_ATTR) {
109       key = null;
110       cf.parseAnnotationsAttr(this, null);
111     }
112   }
113
114   @Override
115   public void setAnnotation (ClassFile cf, Object tag, int annotationIndex, String annotationType) {
116     if (annotationType.equals("Ljava/lang/annotation/Inherited;")) {
117       ai.setInherited( true);
118     }
119   }
120
121   @Override
122   public void setPrimitiveAnnotationValue (ClassFile cf, Object tag, int annotationIndex, int valueIndex,
123           String elementName, int arrayIndex, Object val) {
124     if (arrayIndex >= 0) {
125       valElements[arrayIndex] = val;
126     } else {
127       if (key != null){
128         value = val;
129       }
130     }
131   }
132
133   @Override
134   public void setStringAnnotationValue (ClassFile cf, Object tag, int annotationIndex, int valueIndex,
135           String elementName, int arrayIndex, String val) {
136     if (arrayIndex >= 0) {
137       valElements[arrayIndex] = val;
138     } else {
139       if (key != null){
140         value = val;
141       }
142     }
143   }
144
145   @Override
146   public void setClassAnnotationValue (ClassFile cf, Object tag, int annotationIndex, int valueIndex,
147           String elementName, int arrayIndex, String typeName) {
148     Object val = AnnotationInfo.getClassValue(typeName);
149     if (arrayIndex >= 0) {
150       valElements[arrayIndex] = val;
151     } else {
152       if (key != null){
153         value = val;
154       }
155     }
156   }
157
158   @Override
159   public void setEnumAnnotationValue (ClassFile cf, Object tag, int annotationIndex, int valueIndex,
160           String elementName, int arrayIndex, String enumType, String enumValue) {
161     Object val = AnnotationInfo.getEnumValue(enumType, enumValue);
162     if (arrayIndex >= 0) {
163       valElements[arrayIndex] = val;
164     } else {
165       if (key != null){
166         value = val;
167       }
168     }
169   }
170
171   @Override
172   public void setAnnotationValueElementCount (ClassFile cf, Object tag, int annotationIndex, int valueIndex,
173           String elementName, int elementCount) {
174     valElements = new Object[elementCount];
175   }
176
177   @Override
178   public void setAnnotationValueElementsDone (ClassFile cf, Object tag, int annotationIndex, int valueIndex,
179           String elementName) {
180     if (key != null) {
181       value = valElements;
182     }
183   }
184 }