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.
19 package gov.nasa.jpf.vm;
21 import gov.nasa.jpf.util.ObjectList;
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.List;
28 * common root for ClassInfo, MethodInfo, FieldInfo (and maybe more to follow)
30 * so far, it's used to factorize the annotation support, but we can also
31 * move the attributes up here
33 * Note this is used for both declaration- and type- annotations since there is
34 * a cross-over (type annotations of classes/interfaces are visible through the
35 * reflection API that is otherwise just reserved for declaration annotations)
37 * 2do - there are 3 annotation positions that are valid for both type and declaration
38 * annotations: class/interface, field and formal method parameters. Of these,
39 * only class/interface type annotations can be queried at runtime, i.e. are
40 * treated similarly to declaration annotations. It is not clear if this is a
41 * Java 8 implementation artifact or intentional
43 * Other than annotating classes/interfaces, type and declaration annotations
44 * are kept separate and only the latter ones can be queried from Java, hence
45 * we provide a query API that is only accessible from instructions,
46 * native peers and listeners. Type annotations are used
48 public abstract class InfoObject implements Cloneable {
50 static AnnotationInfo[] NO_ANNOTATIONS = new AnnotationInfo[0];
51 static AbstractTypeAnnotationInfo[] NO_TYPE_ANNOTATIONS = new AbstractTypeAnnotationInfo[0];
53 // the number of annotations per class/method/field is usually
54 // small enough so that simple arrays are more efficient than HashMaps
55 protected AnnotationInfo[] annotations = NO_ANNOTATIONS;
57 protected AbstractTypeAnnotationInfo[] typeAnnotations = NO_TYPE_ANNOTATIONS;
60 * user defined attribute objects.
61 * Note - this is NOT automatically state restored upon backtracking,
62 * subclasses have to do this on their own if required
64 protected Object attr;
67 public void setAnnotations (AnnotationInfo[] annotations){
68 this.annotations = annotations;
71 public void addAnnotations (AnnotationInfo[] annotations){
72 if (annotations == null){
73 this.annotations = annotations;
75 AnnotationInfo[] newAi = new AnnotationInfo[this.annotations.length + annotations.length];
76 System.arraycopy(this.annotations,0,newAi, 0, this.annotations.length);
77 System.arraycopy(annotations, 0, newAi, this.annotations.length, annotations.length);
78 this.annotations = newAi;
82 public void addAnnotation (AnnotationInfo newAnnotation){
83 AnnotationInfo[] ai = annotations;
85 ai = new AnnotationInfo[1];
86 ai[0] = newAnnotation;
89 int len = annotations.length;
90 ai = new AnnotationInfo[len+1];
91 System.arraycopy(annotations, 0, ai, 0, len);
92 ai[len] = newAnnotation;
98 // to be overridden by ClassInfo because of superclass inhertited annotations
99 public boolean hasAnnotations(){
100 return (annotations != NO_ANNOTATIONS);
103 // to be overridden by ClassInfo because of superclass inhertited annotations
104 public AnnotationInfo[] getAnnotations() {
108 // to be overridden by ClassInfo because of superclass inhertited annotations
109 public AnnotationInfo getAnnotation (String name){
110 AnnotationInfo[] ai = annotations;
111 if (ai != NO_ANNOTATIONS){
112 for (int i=0; i<ai.length; i++){
113 if (ai[i].getName().equals(name)){
121 public boolean hasAnnotation (String name){
122 return getAnnotation(name) != null;
125 public AnnotationInfo[] getDeclaredAnnotations(){
129 //--- type annotations
131 public void setTypeAnnotations (AbstractTypeAnnotationInfo[] typeAnnotations){
132 this.typeAnnotations = typeAnnotations;
135 public void addTypeAnnotations (AbstractTypeAnnotationInfo[] tas){
136 if (typeAnnotations == NO_TYPE_ANNOTATIONS){
137 typeAnnotations = tas;
140 int oldLen = typeAnnotations.length;
141 AbstractTypeAnnotationInfo[] newTA = new AbstractTypeAnnotationInfo[oldLen + tas.length];
142 System.arraycopy(typeAnnotations, 0, newTA, 0, oldLen);
143 System.arraycopy(tas, 0, newTA, oldLen, tas.length);
144 typeAnnotations = newTA;
148 public void addTypeAnnotation (AbstractTypeAnnotationInfo newAnnotation){
149 AbstractTypeAnnotationInfo[] ai = typeAnnotations;
151 ai = new AbstractTypeAnnotationInfo[1];
152 ai[0] = newAnnotation;
155 int len = annotations.length;
156 ai = new AbstractTypeAnnotationInfo[len+1];
157 System.arraycopy(annotations, 0, ai, 0, len);
158 ai[len] = newAnnotation;
161 typeAnnotations = ai;
165 public AbstractTypeAnnotationInfo[] getTypeAnnotations() {
166 return typeAnnotations;
169 public boolean hasTypeAnnotations(){
170 return (typeAnnotations != NO_TYPE_ANNOTATIONS);
173 public boolean hasTypeAnnotation (String name){
174 return getTypeAnnotation(name) != null;
177 public AbstractTypeAnnotationInfo getTypeAnnotation (String annoClsName){
178 AbstractTypeAnnotationInfo[] ai = typeAnnotations;
179 if (ai != NO_TYPE_ANNOTATIONS){
180 for (int i=0; i<ai.length; i++){
181 if (ai[i].getName().equals(annoClsName)){
189 public <T extends AbstractTypeAnnotationInfo> List<T> getTargetTypeAnnotations (Class<T> targetType){
192 AbstractTypeAnnotationInfo[] ais = typeAnnotations;
193 if (ais != NO_TYPE_ANNOTATIONS){
194 for (AbstractTypeAnnotationInfo ai : ais){
195 if (targetType.isAssignableFrom(ai.getClass())){
197 list = new ArrayList();
207 return Collections.emptyList();
211 //--- the generic attribute API
213 public boolean hasAttr () {
214 return (attr != null);
217 public boolean hasAttr (Class<?> attrType){
218 return ObjectList.containsType(attr, attrType);
221 public boolean hasAttrValue (Object a){
222 return ObjectList.contains(attr, a);
226 * this returns all of them - use either if you know there will be only
227 * one attribute at a time, or check/process result with ObjectList
229 public Object getAttr(){
234 * this replaces all of them - use only if you know
235 * - there will be only one attribute at a time
236 * - you obtained the value you set by a previous getXAttr()
237 * - you constructed a multi value list with ObjectList.createList()
239 public void setAttr (Object a){
243 public void addAttr (Object a){
244 attr = ObjectList.add(attr, a);
247 public void removeAttr (Object a){
248 attr = ObjectList.remove(attr, a);
251 public void replaceAttr (Object oldAttr, Object newAttr){
252 attr = ObjectList.replace(attr, oldAttr, newAttr);
256 * this only returns the first attr of this type, there can be more
257 * if you don't use client private types or the provided type is too general
259 public <T> T getAttr (Class<T> attrType) {
260 return ObjectList.getFirst(attr, attrType);
263 public <T> T getNextAttr (Class<T> attrType, Object prev) {
264 return ObjectList.getNext(attr, attrType, prev);
267 public ObjectList.Iterator attrIterator(){
268 return ObjectList.iterator(attr);
271 public <T> ObjectList.TypedIterator<T> attrIterator(Class<T> attrType){
272 return ObjectList.typedIterator(attr, attrType);