//
// Copyright (C) 2006 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.lang.reflect.Modifier;
import de.fosd.typechef.featureexpr.FeatureExpr;
/**
* type, name and attribute information of a field.
*/
public abstract class FieldInfo extends InfoObject implements GenericSignatureHolder {
//--- FieldInfo attributes
// don't break transitions on get/putXX insns of this field, even if shared
static final int NEVER_BREAK = 0x10000;
// always break on this field's access if object is shared
// (ignored if NEVER_BREAK is set)
static final int BREAK_SHARED = 0x20000;
// those might relate to sticky ElementInto.ATTR_*
protected int attributes;
protected final String name;
protected String type; // lazy initialized fully qualified type name as per JLS 6.7 ("int", "x.Y[]")
protected final String signature; // "I", "[Lx/Y;" etc.
protected int storageSize;
protected ClassInfo ci; // class this field belongs to
protected int fieldIndex; // declaration ordinal
// where in the corresponding Fields object do we store the value
// (note this works because of the wonderful single inheritance)
protected int storageOffset;
// optional initializer for this field, can't be final because it is set from
// classfile field_info attributes (i.e. after construction)
protected Object cv;
protected String genericSignature;
protected int modifiers;
public static FieldInfo create (String name, String signature, int modifiers){
switch(signature.charAt(0)){
case 'Z':
return new BooleanFieldInfo(name, modifiers);
case 'B':
return new ByteFieldInfo(name, modifiers);
case 'S':
return new ShortFieldInfo(name, modifiers);
case 'C':
return new CharFieldInfo(name, modifiers);
case 'I':
return new IntegerFieldInfo(name, modifiers);
case 'J':
return new LongFieldInfo(name, modifiers);
case 'F':
return new FloatFieldInfo(name, modifiers);
case 'D':
return new DoubleFieldInfo(name, modifiers);
default:
return new ReferenceFieldInfo(name, signature, modifiers);
}
}
protected FieldInfo(String name, String signature, int modifiers) {
this.name = name;
this.signature = signature;
this.modifiers = modifiers;
}
protected void linkToClass (ClassInfo ci, int idx, int off){
this.ci = ci;
this.fieldIndex = idx;
this.storageOffset = off;
}
// those are set subsequently from classfile attributes
public void setConstantValue(Object constValue){
cv = constValue;
}
public abstract String valueToString (Fields f);
public boolean is1SlotField(){
return false;
}
public boolean is2SlotField(){
return false;
}
public boolean isBooleanField() {
return false;
}
public boolean isByteField() {
return false;
}
public boolean isCharField() {
return false;
}
public boolean isShortField() {
return false;
}
public boolean isIntField() {
return false;
}
public boolean isLongField() {
return false;
}
public boolean isFloatField(){
return false;
}
public boolean isDoubleField(){
return false;
}
public boolean isNumericField(){
return false;
}
public boolean isFloatingPointField(){
return false;
}
public boolean isReference () {
return false;
}
public boolean isArrayField () {
return false;
}
/**
* Returns the class that this field is associated with.
*/
public ClassInfo getClassInfo () {
return ci;
}
public Object getConstantValue () {
return cv;
}
public abstract Object getValueObject (Fields data);
public int getModifiers() {
return modifiers;
}
public int getFieldIndex () {
return fieldIndex;
}
/**
* is this a static field? Counter productive to the current class struct,
* but at some point we want to get rid of the Dynamic/Static branch (it's
* really just a field attribute)
*/
public boolean isStatic () {
return (modifiers & Modifier.STATIC) != 0;
}
/**
* is this field declared `final'?
*/
public boolean isFinal () {
return (modifiers & Modifier.FINAL) != 0;
}
public boolean isVolatile () {
return (modifiers & Modifier.VOLATILE) != 0;
}
public boolean isTransient () {
return (modifiers & Modifier.TRANSIENT) != 0;
}
public boolean isPublic () {
return (modifiers & Modifier.PUBLIC) != 0;
}
public boolean isProtected() {
return (modifiers & Modifier.PROTECTED) != 0;
}
public boolean isPrivate() {
return (modifiers & Modifier.PRIVATE) != 0;
}
public boolean isPackagePrivate() {
return !isPrivate() && ! isPublic() && ! isProtected();
}
/**
* Returns the name of the field.
*/
public String getName () {
return name;
}
/**
* @return the storage size of this field, @see Types.getTypeSize
*/
public int getStorageSize () {
return 1;
}
/**
* Returns the type of the field as a fully qualified type name according to JLS 6.7
* ("int", "x.Y[]")
*/
public String getType () {
if (type == null){
type = Types.getTypeName(signature);
}
return type;
}
public byte getTypeCode (){
return Types.getTypeCode(signature);
}
public String getSignature(){
return signature;
}
public String getGenericSignature() {
return genericSignature;
}
public void setGenericSignature(String sig){
genericSignature = sig;
}
public ClassInfo getTypeClassInfo () {
return ClassLoaderInfo.getCurrentResolvedClassInfo(getType());
}
public Class<? extends ChoiceGenerator<?>> getChoiceGeneratorType (){
return null;
}
/**
* pushClinit the corresponding data in the provided Fields instance
*/
public abstract void initialize (FeatureExpr ctx, ElementInfo ei, ThreadInfo ti);
/**
* Returns a string representation of the field.
*/
public String toString () {
StringBuilder sb = new StringBuilder();
if (isStatic()) {
sb.append("static ");
}
if (isFinal()) {
sb.append("final ");
}
//sb.append(Types.getTypeName(type));
sb.append(getType());
sb.append(' ');
sb.append(ci.getName());
sb.append('.');
sb.append(name);
return sb.toString();
}
//--- those are the JPF internal attribute flags (not to mix with free user attrs)
void setAttributes (int a) {
attributes = a;
}
public void addAttribute (int a){
attributes |= a;
}
public int getAttributes () {
return attributes;
}
public boolean breakShared() {
return ((attributes & BREAK_SHARED) != 0);
}
public boolean neverBreak() {
return ((attributes & NEVER_BREAK) != 0);
}
public int getStorageOffset () {
return storageOffset;
}
public String getFullName() {
return ci.getName() + '.' + name;
}
/**
* Creates a field for a given class, by cloning this FieldInfo
* and reseting the class that the field belongs to
*/
public FieldInfo getInstanceFor(ClassInfo ci) {
FieldInfo clone;
try {
clone = (FieldInfo)clone();
clone.ci = ci;
} catch (CloneNotSupportedException cnsx){
cnsx.printStackTrace();
return null;
}
return clone;
}
}