package php.runtime.util;
import php.runtime.lang.Closure;
import php.runtime.loader.RuntimeClassLoader;
import php.runtime.reflection.ClassEntity;
import php.runtime.reflection.FunctionEntity;
import php.runtime.reflection.MethodEntity;
import php.runtime.reflection.ModuleEntity;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class JVMStackTracer implements Iterable<JVMStackTracer.Item> {
protected final RuntimeClassLoader classLoader;
protected final List<Item> result;
public JVMStackTracer(RuntimeClassLoader classLoader, StackTraceElement[] elements){
this.classLoader = classLoader;
this.result = new ArrayList<Item>();
for(StackTraceElement e : elements) {
result.add(new Item(classLoader, e));
}
}
@Override
public Iterator<Item> iterator() {
return result.iterator();
}
public static class Item {
public final String fileName;
public final int lineNumber;
public final ModuleEntity module;
public final ClassEntity clazz;
public final MethodEntity method;
public final FunctionEntity function;
protected final StackTraceElement element;
public Item(RuntimeClassLoader classLoader, StackTraceElement el){
element = el;
fileName = el.getFileName();
lineNumber = el.getLineNumber();
String className = el.getClassName();
FunctionEntity f_e = classLoader.getFunction(className);
String realMethodName = null;
if (el.getMethodName() != null){
if (el.getMethodName().indexOf('$') > -1)
realMethodName = el.getMethodName().substring(0, el.getMethodName().indexOf('$'));
else
realMethodName = el.getMethodName();
realMethodName = realMethodName.toLowerCase();
}
if (f_e != null){
function = f_e;
module = f_e.getModule();
clazz = null;
method = null;
} else {
ClassEntity c_e = classLoader.getClass(className);
if (c_e != null){
clazz = c_e;
function = null;
method = c_e.findMethod(realMethodName);
module = c_e.getModule();
} else {
module = classLoader.getModule(className);
clazz = null;
method = null;
function = null;
}
}
}
public boolean isSystem() {
return element.getClassName().startsWith("sun.");
}
public boolean isInternal(){
return function == null && clazz == null && module == null;
}
public String getSignature() {
String result;
if (function != null)
result = function.getName();
else if (clazz != null && method == null)
result = clazz.getName() + ".<init>";
else if (clazz != null && clazz.isInstanceOf(Closure.class))
result = "<Closure>";
else if (clazz != null)
result = clazz.getName() + "." + method.getName();
else if (module != null)
result = "include ";
else
result = element.getClassName() + "." + element.getMethodName();
return result;
}
@Override
public String toString() {
String result = getSignature();
result = result +
(fileName != null && lineNumber >= 0 ?
"(" + fileName + ":" + lineNumber + ")" :
(fileName != null ? "("+fileName+")" : "(Unknown Source)")
);
return result;
}
}
}