//
// Copyright (C) 2012 United States Government as represented by the
// Administrator of the National Aeronautics and Space Administration
// (NASA). All Rights Reserved.
//
// This software is distributed under the NASA Open Source Agreement
// (NOSA), version 1.3. The NOSA has been approved by the Open Source
// Initiative. See the file NOSA-1.3-JPF at the top of the distribution
// directory tree for the complete NOSA document.
//
// THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY
// KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT
// LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO
// SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
// A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT
// THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT
// DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE.
//
package gov.nasa.jpf.vm;
import java.io.File;
import cmu.conditional.One;
import de.fosd.typechef.featureexpr.FeatureExpr;
import de.fosd.typechef.featureexpr.FeatureExprFactory;
import gov.nasa.jpf.Config;
import gov.nasa.jpf.JPF;
import gov.nasa.jpf.util.JPFLogger;
/**
* @author Nastaran Shafiei <nastaran.shafiei@gmail.com>
*
* Represents the JPF system classloader which models the following hierarchy.
*
* ----------------
* | Bootstrap CL |
* ----------------
* |
* ----------------
* | Extension CL |
* ----------------
* |
* ------------------
* | Application CL |
* ------------------
*
* Since in the standard VM user does not have any control over the built-in
* classloaders hierarchy, in JPF, we model all three by an instance of
* SystemClassLoader which is responsible to load classes from Java API,
* standard extensions packages, and the local file system.
*/
public abstract class SystemClassLoaderInfo extends ClassLoaderInfo {
static JPFLogger log = JPF.getLogger("class");
// we need to keep track of this in case something needs the current SystemClassLoaderInfo before we have a main thread
static SystemClassLoaderInfo lastInstance;
// note that initialization requires these to be startup classes
protected ClassInfo classLoaderClassInfo;
protected ClassInfo objectClassInfo;
protected ClassInfo classClassInfo;
protected ClassInfo stringClassInfo;
protected ClassInfo weakRefClassInfo;
protected ClassInfo refClassInfo;
protected ClassInfo enumClassInfo;
protected ClassInfo threadClassInfo;
protected ClassInfo threadGroupClassInfo;
protected ClassInfo charArrayClassInfo;
protected int unCachedClasses = 10;
public SystemClassLoaderInfo (VM vm, int appId){
super(vm);
lastInstance = this;
// this is a hack - for user ClassLoaderInfos, we compute the id from the corresponding
// objRef of the JPF ClassLoader object. For SystemClassLoaderInfos we can't do that because
// they are created before we can create JPF objects. However, this is safe if we know
// the provided id is never going to be the objRef of a future ClassLoader object, which is
// a safe bet since the first objects created are all system Class objects that are never going to
// be recycled.
this.id = computeId(appId);
initializeSystemClassPath( vm, appId);
}
protected abstract void initializeSystemClassPath (VM vm, int appId);
//--- these can be used to build the app specific system CP
protected File[] getPathElements (Config conf, String keyBase, int appId) {
File[] pathElements = null;
// try appId indexed key first
String key = keyBase + '.' + appId;
if (conf.containsKey(key)) {
pathElements = conf.getPathArray(key);
} else { // fall back to keyBase
pathElements = conf.getPathArray(keyBase);
}
return pathElements;
}
public SystemClassLoaderInfo getSystemClassLoader() {
return this;
}
@Override
public ClassInfo getResolvedClassInfo (FeatureExpr ctx, String clsName){
ClassInfo ci = super.getResolvedClassInfo(ctx, clsName);
if (unCachedClasses > 0){
updateCachedClassInfos(ci);
}
return ci;
}
public boolean isSystemClassLoader() {
return true;
}
static boolean checkClassName (String clsName) {
if ( !clsName.matches("[a-zA-Z_$][a-zA-Z_$0-9.]*")) {
return false;
}
// well, those two could be part of valid class names, but
// in all likeliness somebody specified a filename instead of
// a classname
if (clsName.endsWith(".java")) {
return false;
}
if (clsName.endsWith(".class")) {
return false;
}
return true;
}
@Override
public ClassInfo loadClass(FeatureExpr ctx, String cname) {
return getResolvedClassInfo(ctx, cname);
}
@Override
protected ClassInfo loadSystemClass (String typeName){
return new ClassInfo( typeName, this);
}
protected void setClassLoaderObject (ElementInfo ei){
objRef = ei.getObjectRef();
//id = computeId(objRef);
// cross link
ei.setIntField(FeatureExprFactory.True(), ID_FIELD, new One<>(id));
}
//-- ClassInfos cache management --
protected void updateCachedClassInfos (ClassInfo ci) {
String name = ci.name;
if ((objectClassInfo == null) && name.equals("java.lang.Object")) {
objectClassInfo = ci; unCachedClasses--;
} else if ((classClassInfo == null) && name.equals("java.lang.Class")) {
classClassInfo = ci; unCachedClasses--;
} else if ((classLoaderClassInfo == null) && name.equals("java.lang.ClassLoader")) {
classInfo = ci;
classLoaderClassInfo = ci; unCachedClasses--;
} else if ((stringClassInfo == null) && name.equals("java.lang.String")) {
stringClassInfo = ci; unCachedClasses--;
} else if ((charArrayClassInfo == null) && name.equals("[C")) {
charArrayClassInfo = ci; unCachedClasses--;
} else if ((weakRefClassInfo == null) && name.equals("java.lang.ref.WeakReference")) {
weakRefClassInfo = ci; unCachedClasses--;
} else if ((refClassInfo == null) && name.equals("java.lang.ref.Reference")) {
refClassInfo = ci; unCachedClasses--;
} else if ((enumClassInfo == null) && name.equals("java.lang.Enum")) {
enumClassInfo = ci; unCachedClasses--;
} else if ((threadClassInfo == null) && name.equals("java.lang.Thread")) {
threadClassInfo = ci; unCachedClasses--;
} else if ((threadGroupClassInfo == null) && name.equals("java.lang.ThreadGroup")) {
threadGroupClassInfo = ci; unCachedClasses--;
}
}
protected ClassInfo getObjectClassInfo() {
return objectClassInfo;
}
protected ClassInfo getClassClassInfo() {
return classClassInfo;
}
protected ClassInfo getClassLoaderClassInfo() {
return classLoaderClassInfo;
}
protected ClassInfo getStringClassInfo() {
return stringClassInfo;
}
protected ClassInfo getCharArrayClassInfo() {
return charArrayClassInfo;
}
protected ClassInfo getEnumClassInfo() {
return enumClassInfo;
}
protected ClassInfo getThreadClassInfo() {
return threadClassInfo;
}
protected ClassInfo getThreadGroupClassInfo() {
return threadGroupClassInfo;
}
protected ClassInfo getReferenceClassInfo() {
return refClassInfo;
}
protected ClassInfo getWeakReferenceClassInfo() {
return weakRefClassInfo;
}
}