2 * Copyright (C) 2014, United States Government, as represented by the
3 * Administrator of the National Aeronautics and Space Administration.
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
10 * http://www.apache.org/licenses/LICENSE-2.0.
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.
18 package gov.nasa.jpf.jvm;
20 import java.util.LinkedList;
22 import gov.nasa.jpf.JPFException;
23 import gov.nasa.jpf.vm.AnnotationInfo;
24 import gov.nasa.jpf.vm.AnnotationParser;
25 import gov.nasa.jpf.vm.ClassParseException;
26 import gov.nasa.jpf.vm.Types;
29 * parser that reads annotation classfiles and extracts default value entries
31 * Java annotations form a different type system. Java annotations are essentially
32 * restricted interfaces (no super-interface, no fields other than static finals
33 * that are inlined by the compiler)
35 * Since Java annotations use only a small subset of the Java classfile format
36 * we only have to parse methods and method attributes
38 * <2do> class and enum values are not yet supported
40 public class JVMAnnotationParser extends ClassFileReaderAdapter implements AnnotationParser {
49 String annotationName;
50 AnnotationInfo.Entry[] entries;
52 protected LinkedList<AnnotationInfo> annotationStack;
53 protected AnnotationInfo curAi;
54 protected LinkedList<Object[]> valuesStack;
56 public JVMAnnotationParser (ClassFile cf) {
61 public void parse (AnnotationInfo ai) throws ClassParseException {
67 //--- the overridden ClassFileReader methods
70 public void setClass (ClassFile cf, String clsName, String superClsName, int flags, int cpCount) throws ClassParseException {
72 annotationName = Types.getClassNameFromTypeName(clsName);
74 ai.setName(annotationName);
78 public void setInterface (ClassFile cf, int ifcIndex, String ifcName) {
79 if (!"java/lang/annotation/Annotation".equals(ifcName)) {
80 throw new JPFException("illegal annotation interface of: " + annotationName + " is " + ifcName);
85 public void setMethodCount (ClassFile cf, int methodCount) {
86 entries = new AnnotationInfo.Entry[methodCount];
90 public void setMethod (ClassFile cf, int methodIndex, int accessFlags, String name, String descriptor) {
96 public void setMethodDone (ClassFile cf, int methodIndex){
97 entries[methodIndex] = new AnnotationInfo.Entry(key, value);
101 public void setMethodsDone (ClassFile cf){
102 ai.setEntries(entries);
106 public void setMethodAttribute (ClassFile cf, int methodIndex, int attrIndex, String name, int attrLength) {
107 if (name == ClassFile.ANNOTATIONDEFAULT_ATTR) {
108 cf.parseAnnotationDefaultAttr(this, key);
113 public void setClassAttribute (ClassFile cf, int attrIndex, String name, int attrLength) {
114 if (name == ClassFile.RUNTIME_VISIBLE_ANNOTATIONS_ATTR) {
116 cf.parseAnnotationsAttr(this, null);
121 public void setAnnotation (ClassFile cf, Object tag, int annotationIndex, String annotationType) {
122 if (key == null && annotationType.equals("Ljava/lang/annotation/Inherited;")) {
123 ai.setInherited( true);
125 if(key != null && annotationIndex == -1) {
126 if(annotationStack == null) {
127 assert valuesStack == null;
128 annotationStack = new LinkedList<>();
129 valuesStack = new LinkedList<>();
131 annotationStack.addFirst(curAi);
132 valuesStack.addFirst(valElements);
134 curAi = ai.getClassLoaderInfo().getResolvedAnnotationInfo(Types.getClassNameFromTypeName(annotationType));
139 public void setAnnotationFieldValue(ClassFile cf, Object tag, int annotationIndex, int valueIndex, String elementName, int arrayIndex) {
140 assert annotationStack.size() > 0;
141 AnnotationInfo ai = curAi;
142 valElements = valuesStack.pop();
143 curAi = annotationStack.pop();
144 if(arrayIndex >= 0) {
145 valElements[arrayIndex] = ai;
148 curAi.setClonedEntryValue(elementName, ai);
156 public void setPrimitiveAnnotationValue (ClassFile cf, Object tag, int annotationIndex, int valueIndex,
157 String elementName, int arrayIndex, Object val) {
158 if (arrayIndex >= 0) {
159 valElements[arrayIndex] = val;
160 } else if(curAi != null) {
161 curAi.setClonedEntryValue(elementName, val);
170 public void setStringAnnotationValue (ClassFile cf, Object tag, int annotationIndex, int valueIndex,
171 String elementName, int arrayIndex, String val) {
172 if (arrayIndex >= 0) {
173 valElements[arrayIndex] = val;
174 } else if(curAi != null) {
175 curAi.setClonedEntryValue(elementName, val);
184 public void setClassAnnotationValue (ClassFile cf, Object tag, int annotationIndex, int valueIndex,
185 String elementName, int arrayIndex, String typeName) {
186 Object val = AnnotationInfo.getClassValue(typeName);
187 if (arrayIndex >= 0) {
188 valElements[arrayIndex] = val;
189 } else if(curAi != null) {
190 curAi.setClonedEntryValue(elementName, val);
199 public void setEnumAnnotationValue (ClassFile cf, Object tag, int annotationIndex, int valueIndex,
200 String elementName, int arrayIndex, String enumType, String enumValue) {
201 Object val = AnnotationInfo.getEnumValue(enumType, enumValue);
202 if (arrayIndex >= 0) {
203 valElements[arrayIndex] = val;
204 } else if(curAi != null) {
205 curAi.setClonedEntryValue(elementName, val);
214 public void setAnnotationValueElementCount (ClassFile cf, Object tag, int annotationIndex, int valueIndex,
215 String elementName, int elementCount) {
216 valElements = new Object[elementCount];
220 public void setAnnotationValueElementsDone (ClassFile cf, Object tag, int annotationIndex, int valueIndex,
221 String elementName) {
223 curAi.setClonedEntryValue(elementName, valElements);
224 } else if (key != null) {