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 org.nanovm.converter.ClassFileReader;
import org.nanovm.converter.ClassInfo;
import java.io.*;
import java.util.Vector;
import java.util.StringTokenizer;
public class ClassLoader {
static private Vector<ClassInfo> classes = new Vector<ClassInfo>();
static private String classPath = null;
static public void setClassPath(String path) {
classPath = path;
}
public static ClassInfo getClassInfo(int index) {
return (ClassInfo)classes.elementAt(index);
}
public static ClassInfo getClassInfo(String className) {
// search through all classes
for(int i=0;i<classes.size();i++) {
if(getClassInfo(i).getName().equals(className))
return getClassInfo(i);
}
return null;
}
// in an uvm file all methods of all classes are stored after each other
// this method returns the class index from the method index in this list
public static ClassInfo getClassInfoFromMethodIndex(int index) {
int classIndex = 0;
// search through all classes
while(index >= getClassInfo(classIndex).methods())
index -= getClassInfo(classIndex++).methods();
return getClassInfo(classIndex);
}
// get index of class named className
public static int getClassIndex(String className) {
// search through all classes
for(int i=0;i<classes.size();i++) {
if(getClassInfo(i).getName().equals(className))
return i;
}
return -1;
}
public static boolean methodExists(String className,
String name, String type) {
// search through all classes
for(int i=0;i<classes.size();i++) {
ClassInfo classInfo = getClassInfo(i);
if((classInfo.getName().equals(className)) &&
(classInfo.providesMethod(name, type)))
return true;
}
return false;
}
// search through all classes and return index of matching method
public static int getMethodIndex(String className, String name, String type) {
for(int i=0, index=0;i<classes.size();i++) {
if(getClassInfo(i).getName().equals(className)) {
index += getClassInfo(i).getMethodIndex(name, type);
return index;
} else
index += getClassInfo(i).methods();
}
return -1;
}
public static boolean fieldExistsExact(String className,
String name, String type) {
// search through all classes
for(int i=0;i<classes.size();i++) {
ClassInfo classInfo = getClassInfo(i);
if((classInfo.getName().equals(className)) &&
(classInfo.providesField(name, type)))
return true;
}
return false;
}
public static boolean fieldExists(String className,
String name, String type) {
while (className!=null) {
if (fieldExistsExact(className, name, type))
return true;
className = getSuperClassName(className);
}
return false;
}
public static FieldInfo getFieldInfoExact(String className,
String name, String type) {
// search through all classes
for(int i=0;i<classes.size();i++) {
ClassInfo classInfo = getClassInfo(i);
if(classInfo.getName().equals(className))
return classInfo.getFieldInfo(name, type);
}
return null;
}
public static FieldInfo getFieldInfo(String className,
String name, String type) {
while (className!=null) {
FieldInfo result = getFieldInfoExact(className, name, type);
if (result!=null)
return result;
className = getSuperClassName(className);
}
return null;
}
public static String getSuperClassName(String className) {
// search through all classes
for(int i=0;i<classes.size();i++) {
ClassInfo classInfo = getClassInfo(i);
if(classInfo.getName().equals(className))
return classInfo.getSuperClassName();
}
return null;
}
// search for a static field and sum up all static fields before,
// this gives us the offset to this static field in the table
// of all static fields of our set of class files
public static int getStaticFieldIndex(String className,
String name, String type) {
// search through all classes
for(int i=0, cnt=0;i<classes.size();i++) {
ClassInfo classInfo = getClassInfo(i);
if(classInfo.getName().equals(className))
return cnt + classInfo.getFieldIndex(AccessFlags.STATIC, name, type);
else
cnt += classInfo.staticFields();
}
return -1;
}
// get total methods of all classes
public static int totalMethods() {
int num = 0;
for(int i=0;i<classes.size();i++)
num += getClassInfo(i).methods();
return num;
}
// TODO:
public static int totalConstantEntries() {
int sum = 0;
for(int i=0;i<classes.size();i++)
sum += getClassInfo(i).getConstPool().totalConstantEntries();
return sum;
}
public static int getConstantEntry(int index) {
int i=0;
// search through all classes
while(index >= getClassInfo(i).getConstPool().totalConstantEntries())
index -= getClassInfo(i++).getConstPool().totalConstantEntries();
return getClassInfo(i).getConstPool().getConstantEntry(index);
}
// get memory required to store all strings
public static int totalStringSize() {
int sum = 0;
for(int i=0;i<classes.size();i++)
sum += getClassInfo(i).getConstPool().totalStringSize();
return sum;
}
// get memory required to store all strings
public static int totalStrings() {
int sum = 0;
for(int i=0;i<classes.size();i++)
sum += getClassInfo(i).getConstPool().totalStrings();
return sum;
}
public static String getString(int index) {
int i=0;
// search through all classes
while(index >= getClassInfo(i).getConstPool().totalStrings())
index -= getClassInfo(i++).getConstPool().totalStrings();
return getClassInfo(i).getConstPool().getString(index);
}
// total number of static fields
public static int totalStaticFields() {
int sum = 0;
for(int i=0;i<classes.size();i++) {
ClassInfo classInfo = getClassInfo(i);
sum += classInfo.staticFields();
}
return sum;
}
// return index of main method (must be in class 0, since
// it is the one the user gave as an argument)
public static int getMainIndex() {
return getClassInfo(0).getMethodIndex("main", "([Ljava/lang/String;)V");
}
public static MethodInfo getMethod(int index) {
int i=0;
// search through all classes
while(index >= getClassInfo(i).methods())
index -= getClassInfo(i++).methods();
return(getClassInfo(i).getMethod(index));
}
public static int totalClasses() {
return classes.size();
}
// get class index of method with index
public static int getClassIndex(int index) {
int i=0;
// search through all classes
while(index >= getClassInfo(i).methods())
index -= getClassInfo(i++).methods();
return i;
}
public static void constantRelocate(int i) {
System.out.println("request to relocate " + i);
}
static public void load(String name) {
try {
InputStream is = null;
// walk through all paths stored in classpath
StringTokenizer pathTokenizer
= new StringTokenizer(classPath, File.pathSeparator);
while((pathTokenizer.hasMoreElements()) && (is == null)) {
String filename;
// build full class file name
filename = pathTokenizer.nextToken();
filename += "/";
filename += name;
filename += ".class";
try {
// load given class
is = new FileInputStream(filename);
} catch(FileNotFoundException e) {
is = null;
}
}
if (is == null) {
throw new FileNotFoundException("Unable to find class file " + name + ".class");
}
System.out.println("Loading class " + name );
ClassInfo classInfo = new ClassInfo();
new ClassFileReader().read(is, classInfo);
is.close();
classes.addElement(classInfo);
System.out.println("Checking dependencies ...");
// go through all constants and check for method references
classInfo.getConstPool().resolveMethodRefs();
} catch(Exception e) {
System.out.println("Error loading class: " + e.toString());
System.exit(-1);
}
}
}