ce2866aedfbbbb7adfb76983ab5a1c42b65913fb
[jpf-core.git] / src / main / gov / nasa / jpf / vm / SystemClassLoaderInfo.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.vm;
19
20 import gov.nasa.jpf.Config;
21 import gov.nasa.jpf.JPF;
22 import gov.nasa.jpf.util.JPFLogger;
23
24 import java.io.File;
25 import java.util.ArrayList;
26 import java.util.List;
27
28 /**
29  * @author Nastaran Shafiei <nastaran.shafiei@gmail.com>
30  * 
31  * Represents the JPF system classloader which models the following hierarchy.
32  * 
33  *            ----------------
34  *            | Bootstrap CL |
35  *            ----------------
36  *                   |
37  *            ----------------
38  *            | Extension CL |
39  *            ----------------
40  *                   |
41  *           ------------------
42  *           | Application CL |
43  *           ------------------
44  *           
45  * Since in the standard VM user does not have any control over the built-in 
46  * classloaders hierarchy, in JPF, we model all three by an instance of 
47  * SystemClassLoader which is responsible to load classes from Java API, 
48  * standard extensions packages, and the local file system.     
49  */
50 public abstract class SystemClassLoaderInfo extends ClassLoaderInfo {
51
52   static JPFLogger log = JPF.getLogger("class");
53   
54   // we need to keep track of this in case something needs the current SystemClassLoaderInfo before we have a main thread
55   static SystemClassLoaderInfo lastInstance;  
56   
57   // note that initialization requires these to be startup classes
58   protected ClassInfo classLoaderClassInfo;
59   protected ClassInfo objectClassInfo;
60   protected ClassInfo classClassInfo;
61   protected ClassInfo stringClassInfo;
62   protected ClassInfo weakRefClassInfo;
63   protected ClassInfo refClassInfo;
64   protected ClassInfo enumClassInfo;
65   protected ClassInfo threadClassInfo;
66   protected ClassInfo threadGroupClassInfo;
67   protected ClassInfo charArrayClassInfo;
68
69   protected int unCachedClasses = 10;
70   
71   /**
72    * list of configurable Attributors for ClassInfos, MethodInfos and FieldInfos
73    * that are consulted after creating the ClassInfo but before notifying classLoaded() listeners
74    */
75   protected List<Attributor> attributors;
76   
77   
78   public SystemClassLoaderInfo (VM vm, int appId){
79      super(vm);
80
81      lastInstance = this;
82
83     // this is a hack - for user ClassLoaderInfos, we compute the id from the corresponding
84     // objRef of the JPF ClassLoader object. For SystemClassLoaderInfos we can't do that because
85     // they are created before we can create JPF objects. However, this is safe if we know
86     // the provided id is never going to be the objRef of a future ClassLoader object, which is
87     // a safe bet since the first objects created are all system Class objects that are never going to
88     // be recycled.
89     this.id = computeId(appId);
90     
91     initializeSystemClassPath( vm, appId);
92     initializeAttributors( vm, appId);
93   }
94   
95   protected abstract void initializeSystemClassPath (VM vm, int appId);
96   
97   protected void initializeAttributors (VM vm, int appId){
98     attributors = new ArrayList<Attributor>();
99     
100     Config conf = vm.getConfig();
101     String key = conf.getIndexableKey("vm.attributors", appId);
102     if (key != null){
103       for (Attributor a : conf.getInstances(key, Attributor.class)){
104         attributors.add(a);
105       }
106     }
107   }
108
109   public void addAttributor (Attributor a){
110     attributors.add(a);
111   }
112   
113   /**
114    * to be called on each ClassInfo created in the realm of this SystemClassLoader
115    */
116   @Override
117   protected void setAttributes (ClassInfo ci){
118     for (Attributor a: attributors){
119       a.setAttributes(ci);
120     }
121   }
122   
123   //--- these can be used to build the app specific system CP
124   protected File[] getPathElements (Config conf, String keyBase, int appId) {
125     File[] pathElements = null;
126
127     // try appId indexed key first
128     String key = keyBase + '.' + appId;
129     if (conf.containsKey(key)) {
130       pathElements = conf.getPathArray(key);
131
132     } else { // fall back to keyBase
133       pathElements = conf.getPathArray(keyBase);
134     }
135
136     return pathElements;
137   }
138   
139   @Override
140   public SystemClassLoaderInfo getSystemClassLoader() {
141     return this;
142   }
143
144   
145   @Override
146   public ClassInfo getResolvedClassInfo (String clsName){
147     ClassInfo ci = super.getResolvedClassInfo(clsName);
148     
149     if (unCachedClasses > 0){
150       updateCachedClassInfos(ci);
151     }
152     
153     return ci;
154   }
155
156   @Override
157   public boolean isSystemClassLoader() {
158     return true;
159   }
160
161   static boolean checkClassName (String clsName) {
162     if ( !clsName.matches("[a-zA-Z_$][a-zA-Z_$0-9.]*")) {
163       return false;
164     }
165
166     // well, those two could be part of valid class names, but
167     // in all likeliness somebody specified a filename instead of
168     // a classname
169     if (clsName.endsWith(".java")) {
170       return false;
171     }
172     if (clsName.endsWith(".class")) {
173       return false;
174     }
175
176     return true;
177   }
178   
179
180   @Override
181   public ClassInfo loadClass(String cname) {
182     return getResolvedClassInfo(cname);
183   }
184
185   @Override
186   protected ClassInfo loadSystemClass (String typeName){
187     return new ClassInfo( typeName, this);
188   }
189
190   protected void setClassLoaderObject (ElementInfo ei){
191     objRef = ei.getObjectRef();
192     //id = computeId(objRef);
193     
194     // cross link
195     ei.setIntField(ID_FIELD, id);
196   }
197   
198
199   //-- ClassInfos cache management --
200
201   protected void updateCachedClassInfos (ClassInfo ci) {
202     String name = ci.name;
203
204     if ((objectClassInfo == null) && name.equals("java.lang.Object")) {
205       objectClassInfo = ci; unCachedClasses--;
206     } else if ((classClassInfo == null) && name.equals("java.lang.Class")) {
207       classClassInfo = ci; unCachedClasses--;
208     } else if ((classLoaderClassInfo == null) && name.equals("java.lang.ClassLoader")) {
209       classInfo = ci;
210       classLoaderClassInfo = ci;  unCachedClasses--;
211     } else if ((stringClassInfo == null) && name.equals("java.lang.String")) {
212       stringClassInfo = ci; unCachedClasses--;
213     } else if ((charArrayClassInfo == null) && name.equals("[C")) {
214       charArrayClassInfo = ci; unCachedClasses--;
215     } else if ((weakRefClassInfo == null) && name.equals("java.lang.ref.WeakReference")) {
216       weakRefClassInfo = ci; unCachedClasses--;
217     } else if ((refClassInfo == null) && name.equals("java.lang.ref.Reference")) {
218       refClassInfo = ci; unCachedClasses--;
219     } else if ((enumClassInfo == null) && name.equals("java.lang.Enum")) {
220       enumClassInfo = ci; unCachedClasses--;
221     } else if ((threadClassInfo == null) && name.equals("java.lang.Thread")) {
222       threadClassInfo = ci; unCachedClasses--;
223     } else if ((threadGroupClassInfo == null) && name.equals("java.lang.ThreadGroup")) {
224       threadGroupClassInfo = ci; unCachedClasses--;
225     }
226   }
227   
228   protected ClassInfo getObjectClassInfo() {
229     return objectClassInfo;
230   }
231
232   protected ClassInfo getClassClassInfo() {
233     return classClassInfo;
234   }
235
236   protected ClassInfo getClassLoaderClassInfo() {
237     return classLoaderClassInfo;
238   }
239
240   protected ClassInfo getStringClassInfo() {
241     return stringClassInfo;
242   }
243   
244   protected ClassInfo getCharArrayClassInfo() {
245     return charArrayClassInfo;
246   }
247
248   protected ClassInfo getEnumClassInfo() {
249     return enumClassInfo;
250   }
251
252   protected ClassInfo getThreadClassInfo() {
253     return threadClassInfo;
254   }
255
256   protected ClassInfo getThreadGroupClassInfo() {
257     return threadGroupClassInfo;
258   }
259
260   protected ClassInfo getReferenceClassInfo() {
261     return refClassInfo;
262   }
263
264   protected ClassInfo getWeakReferenceClassInfo() {
265     return weakRefClassInfo;
266   }
267
268 }