/*
* This file is part of the X10 project (http://x10-lang.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* This file was originally derived from the Polyglot extensible compiler framework.
*
* (C) Copyright 2000-2007 Polyglot project group, Cornell University
* (C) Copyright IBM Corporation 2007-2012.
*/
package polyglot.types.reflect;
import polyglot.types.*;
import java.util.*;
import java.io.*;
import java.lang.reflect.Modifier;
/**
* Field models a field (member variable) in a class. The Field class
* grants access to information such as the field's modifiers, its name
* and type descriptor (represented as indices into the constant pool),
* and any attributes of the field. Static fields have a ConstantValue
* attribute.
*
* @see polyglot.types.reflect ConstantValue
*
* @author Nate Nystrom
* (<a href="mailto:nystrom@cs.purdue.edu">nystrom@cs.purdue.edu</a>)
*/
public class Field {
protected DataInputStream in;
protected ClassFile clazz;
protected int modifiers;
protected int name;
protected int type;
protected Attribute[] attrs;
protected ConstantValueAttr constantValue;
protected Signature signature;
protected boolean synthetic;
/**
* Constructor. Read a field from a class file.
*
* @param in
* The data stream of the class file.
* @param clazz
* The class file containing the field.
* @exception IOException
* If an error occurs while reading.
*/
Field(DataInputStream in, ClassFile clazz)
throws IOException
{
this.clazz = clazz;
this.in = in;
}
public void initialize() throws IOException {
modifiers = in.readUnsignedShort();
name = in.readUnsignedShort();
type = in.readUnsignedShort();
int numAttributes = in.readUnsignedShort();
attrs = new Attribute[numAttributes];
for (int i = 0; i < numAttributes; i++) {
int nameIndex = in.readUnsignedShort();
int length = in.readInt();
Constant name = clazz.getConstants()[nameIndex];
if (name != null) {
if ("ConstantValue".equals(name.value())) {
constantValue = new ConstantValueAttr(in, nameIndex, length);
attrs[i] = constantValue;
}
if ("Synthetic".equals(name.value())) {
synthetic = true;
}
if ("Signature".equals(name.value())) {
signature = new Signature(clazz, in, nameIndex, length);
attrs[i] = signature;
}
}
if (attrs[i] == null) {
long n = in.skip(length);
if (n != length) {
throw new EOFException();
}
}
}
}
/**
* Return true of t is java.lang.String.
* We don't compare against ts.String() because ts.String() may not
* yet be set.
*/
public boolean isString(Type t) {
return t.isClass()
&& t.toClass().isTopLevel()
&& t.toClass().fullName().equals(QName.make("java.lang.String"));
}
public boolean isSynthetic() {
return synthetic;
}
public boolean isConstant() {
return this.constantValue != null;
}
public Constant constantValue() {
if (this.constantValue != null) {
int index = this.constantValue.getIndex();
return clazz.getConstants()[index];
}
return null;
}
public int getInt() throws SemanticException {
Constant c = constantValue();
if (c != null && c.tag() == Constant.INTEGER) {
Integer v = (Integer) c.value();
return v.intValue();
}
throw new SemanticException("Could not find expected constant " +
"pool entry with tag INTEGER.");
}
public float getFloat() throws SemanticException {
Constant c = constantValue();
if (c != null && c.tag() == Constant.FLOAT) {
Float v = (Float) c.value();
return v.floatValue();
}
throw new SemanticException("Could not find expected constant " +
"pool entry with tag FLOAT.");
}
public double getDouble() throws SemanticException {
Constant c = constantValue();
if (c != null && c.tag() == Constant.DOUBLE) {
Double v = (Double) c.value();
return v.doubleValue();
}
throw new SemanticException("Could not find expected constant " +
"pool entry with tag DOUBLE.");
}
public long getLong() throws SemanticException {
Constant c = constantValue();
if (c != null && c.tag() == Constant.LONG) {
Long v = (Long) c.value();
return v.longValue();
}
throw new SemanticException("Could not find expected constant " +
"pool entry with tag LONG.");
}
public String getString() throws SemanticException {
Constant c = constantValue();
if (c != null && c.tag() == Constant.STRING) {
Integer i = (Integer) c.value();
c = clazz.getConstants()[i.intValue()];
if (c != null && c.tag() == Constant.UTF8) {
String v = (String) c.value();
return v;
}
}
throw new SemanticException("Could not find expected constant " +
"pool entry with tag STRING or UTF8.");
}
public Attribute[] getAttrs() {
return attrs;
}
public ClassFile getClazz() {
return clazz;
}
public ConstantValueAttr getConstantValue() {
return constantValue;
}
public int getModifiers() {
return modifiers;
}
public int getName() {
return name;
}
public int getType() {
return type;
}
public Signature getSignature() {
return signature;
}
public String name() {
return (String) clazz.getConstants()[this.name].value();
}
public String signature() {
if (this.signature != null) {
return (String) clazz.getConstants()[this.signature.getSignature()].value();
}
return (String) clazz.getConstants()[this.type].value();
}
public String toString() {
return Modifier.toString(modifiers)+"("+Integer.toHexString(modifiers)+") "+name()+signature();
}
}