package org.nanovm.converter;
//
// NanoVMTool, Converter and Upload Tool for the NanoVM
// Copyright (C) 2005 by Till Harbaum <Till@Harbaum.org>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// Parts of this tool are based on public domain code written by Kimberley
// Burchett: http://www.kimbly.com/code/classfile/
//
import java.util.Vector;
/**
* A class for storing information about a class.
* This information can be read in by a ClassFileReader, or written out by
* a ClassFileWriter.
*
* @see FieldInfo
* @see MethodInfo
* @see AttributeInfo
* @see ClassFileReader
* @see ClassFileWriter
*/
public class ClassInfo extends CommonInfo {
private final ClassLoader classLoader;
private String superName = "java.lang.Object";
private String sourceFile;
private ConstPool cp;
// Vector of Strings
private Vector<String> interfaces = new Vector<String>();
// Vector of FieldInfo
private Vector<FieldInfo> fields = new Vector<FieldInfo>();
// Vector of MethodInfo
private Vector<MethodInfo> methods = new Vector<MethodInfo>();
private InnerClassInfo[] innerClasses;
public ClassInfo(ClassLoader classLoader){
this.classLoader = classLoader;
}
public ClassLoader getClassLoader(){
return classLoader;
}
/**
* Set the constant pool. The ClassInfo class itself does not actually use
* the ConstPool for anything. This method is useful if the ClassInfo is
* being read in by a ClassFileReader and there are attributes that the
* Reader does not understand, which reference entries in the constant
* pool. The best example of such an attribute is method bytecodes.
* In a future release, ClassFileReaders will understand bytecodes,
* and so this method will become less important.
* <p/>
* <p>The new ConstPool is not immutable. It may be passed to a
* ClassFileWriter, which will add entries as needed.
*
* @see ConstPool
*/
public void setConstPool(ConstPool cp) {
this.cp = cp;
}
/**
* Get the constant pool. The ClassInfo class itself does not use the
* constant pool for anthing. The constant pool is useful if the ClassInfo is
* being written out by a ClassFileWriter and there are attributes that the
* Writer does not understand, which reference entries in the constant
* pool. The best example of such an attribute is method bytecodes.
* The Writer will use the ConstPool returned by this method in preference
* to creating its own ConstPool. Letting the Writer create its own
* ConstPool is probably not a good idea, for the reasons describe above.
* In a future release, ClassFileWriters will understand bytecodes, and so
* this method will become less important.
*
* @see ConstPool
*/
public ConstPool getConstPool() {
return cp;
}
/**
* Set the name of the super class. The name should be of the form "java.lang.String".
*/
public void setSuperClassName(String name) {
superName = name;
}
/**
* Get the name of the super class. The name is of the form "java.lang.String".
*/
public String getSuperClassName() {
return superName;
}
/**
* Add an interface that the class implements.
*/
public void addInterface(String interfaceName) {
interfaces.addElement(interfaceName);
}
/**
* Get the interfaces that this class implements.
*/
public String[] getInterfaces() {
String[] list = new String[interfaces.size()];
interfaces.copyInto(list);
return list;
}
/**
* Add a field to this class. The FieldInfo should be need not be
* entirely filled out before being added.
*
* @see FieldInfo
*/
public void addField(FieldInfo fieldInfo) {
fields.addElement(fieldInfo);
}
// get field number n
public FieldInfo getField(int index) {
return fields.elementAt(index);
}
/**
*/
public void addMethod(MethodInfo methodInfo) {
methods.addElement(methodInfo);
}
public MethodInfo getMethod(int index) {
return methods.elementAt(index);
}
// return index of given method within current class
public int getMethodIndex(MethodInfo methodInfo) {
for (int i = 0; i < methods.size(); i++)
if (getMethod(i) == methodInfo)
return i;
return -1;
}
// get index of method with specified name/type
public int getMethodIndex(String name, String type) {
for (int i = 0; i < methods.size(); i++) {
MethodInfo methodInfo = methods.elementAt(i);
if (methodInfo.getName().equals(name)) {
if (type == null) return i;
if (methodInfo.getSignature().equals(type))
return i;
}
}
return -1;
}
public int methods() {
return methods.size();
}
public boolean providesMethod(String name, String type) {
for (int i = 0; i < methods.size(); i++) {
MethodInfo methodInfo = methods.elementAt(i);
if (methodInfo.getName().equals(name)) {
if (type == null) return true;
if (methodInfo.getSignature().equals(type))
return true;
}
}
return false;
}
public boolean providesField(String name, String type) {
for (int i = 0; i < fields.size(); i++) {
FieldInfo fieldInfo = fields.elementAt(i);
if (fieldInfo.getName().equals(name)) {
if (type == null) return true;
if (fieldInfo.getSignature().equals(type))
return true;
}
}
return false;
}
public FieldInfo getFieldInfo(String name, String type) {
for (int i = 0; i < fields.size(); i++) {
FieldInfo fieldInfo = fields.elementAt(i);
if (fieldInfo.getName().equals(name)) {
if (type == null) return fieldInfo;
if (fieldInfo.getSignature().equals(type))
return fieldInfo;
}
}
return null;
}
// return number of static fields of this class
public int staticFields() {
int sum = 0;
for (int i = 0; i < fields.size(); i++)
if ((getField(i).getAccessFlags() & AccessFlags.STATIC) != 0)
sum++;
return sum;
}
public int getFieldIndex(int staticFlag, String name, String type) {
int cnt = 0;
for (int i = 0; i < fields.size(); i++) {
FieldInfo fieldInfo = fields.elementAt(i);
if ((getField(i).getAccessFlags() & AccessFlags.STATIC) == staticFlag) {
if (fieldInfo.getName().equals(name) &&
fieldInfo.getSignature().equals(type))
return cnt;
cnt++;
}
}
return -1;
}
// return number of non-static fields of this class
public int nonStaticFields() {
int sum = 0;
for (int i = 0; i < fields.size(); i++)
if ((getField(i).getAccessFlags() & AccessFlags.STATIC) == 0)
sum++;
// add fields of super classes (only for non-native classes)
if (getSuperClassIndex() < classLoader.lowestNativeId)
sum += getClassLoader().getClassInfo(getSuperClassIndex()).nonStaticFields();
return sum;
}
public int getSuperClassIndex() {
int index = getClassLoader().getClassIndex(getSuperClassName());
// no such class in the local classes, try native
if (index < 0)
index = classLoader.getNativeClassId(getSuperClassName());
return index;
}
/**
* Specify the source file for this class, if it is known.
*/
public void setSourceFile(String sourceFile) {
this.sourceFile = sourceFile;
}
/**
* Get the source file for this class. If the file is not known, this
* may return null.
*/
public String getSourceFile() {
return sourceFile;
}
/**
* Set the inner class information of this class. Using inner classes is
* a bit tricky. The array should include elements for every inner class
* of this class, and every class that contains this class. For example:
* <p/>
* <pre>class Foo {
* class Bar {
* class Quux {
* class Squish {
* }
* }
* }
* class Baz {
* }
* }</pre>
* <p/>
* If this ClassInfo is for Foo.Bar, then the inner classes array should be
* {FooInfo, BarInfo, QuuxInfo}. The order is important: outer classes
* <strong>must</strong> come before their inner classes. Note that the
* current class must have an entry in the array. Squish and Baz may be
* included in the array, but they're not necessary.
*
* @see InnerClassInfo
*/
public void setInnerClasses(InnerClassInfo[] innerClasses) {
this.innerClasses = innerClasses;
}
/**
* Get the inner class information of this class.
*
* @see #setInnerClasses()
*/
public InnerClassInfo[] getInnerClasses() {
return innerClasses;
}
}