/* DebugifyingClassLoader.java
Copyright 2003, Bil Lewis
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
*/
/*
* DebugifyingClassLoader.java
*
*/
package com.lambda.Debugger;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.PrintStream;
import org.apache.bcel.Repository;
import org.apache.bcel.classfile.ClassParser;
import org.apache.bcel.classfile.JavaClass;
public class DebugifyingClassLoader extends java.lang.ClassLoader {
static private PrintStream out = System.out;
static private VectorD dontInstrument = new VectorD();
static {
dontInstrument.add("java.");
dontInstrument.add("sun.");
dontInstrument.add("apple.");
dontInstrument.add("javax.");
dontInstrument.add("JAVAX.");
dontInstrument.add("org.apache.bcel");
dontInstrument.add("com.lambda.Debugger");
dontInstrument.add("edu.insa.LSD");
dontInstrument.add("lambda.Debugger");
dontInstrument.add("insa.LSD");
}
static private int depth = 0;
static private String[] spaces = { "", " ", " ", " ", " ",
" ", " ", " ", " ", " ",
" " };
private static void println(String s) {
System.out.println(s);
}
private static String spaces(int i) {
if (i < 0)
return spaces[0];
if (i < 10)
return spaces[i];
return spaces[10];
}
private static String spacesPlus() {
depth++;
return spaces(depth - 1);
}
private static String spacesMinus() {
depth--;
return spaces(depth);
}
private static String spacesExact() {
return spaces(depth - 1);
}
private boolean dontInstrument(String className) {
for (int i = 0; i < dontInstrument.size(); i++) {
if (className.startsWith((String) dontInstrument.elementAt(i)))
return true;
}
return false;
}
protected Class loadClass(String className, boolean resolve)
throws java.lang.ClassNotFoundException {
Class clazz;
boolean instrument = true;
clazz = findLoadedClass(className);
if (clazz != null)
return clazz;
if ((!className.startsWith("javax.xml."))
&& (dontInstrument(className) || (!Debugger.INSTRUMENT))) {
clazz = getParent().loadClass(className);
if (Debugger.TRACE_LOADER)
println("loaded via parent: " + getParent() + " " + className);
return clazz;
}
if (Debugger.TRACE_LOADER)
println(spacesPlus() + "DebugifyingClassLoader loading: "
+ className);
try {
clazz = findClass(className, instrument);
} catch (VerifyError ve) {
println(spacesMinus() + "The ODB cannot instrument: " + className
+ ". Please report bug.\n" + ve);
if (Debugger.TRACE_LOADER)
ve.printStackTrace();
clazz = getParent().loadClass(className);
}
if (clazz == null)
throw new java.lang.ClassNotFoundException(className); // return
// null;
if (resolve)
resolveClass(clazz);
return clazz;
}
public static byte[] debugify(String className, byte[] bytes) {
if (!Debugger.INSTRUMENT)
return bytes;
if (Debugger.TRACE_LOADER)
println("debugifying " + className);
ClassParser parser = new ClassParser(new ByteArrayInputStream(bytes),
"<generated>");
JavaClass javaClass;
try {
javaClass = parser.parse();
} catch (IOException e) {
System.out.println("IMPOSSIBLE");
e.printStackTrace();
return bytes;
}
Class clazz;
if (javaClass == null)
return null;
if (Debugger.TRACE_LOADER)
println(spacesExact() + "DebugifyingClassLoader debugifying: "
+ className);
if (Debugger.TRACE_LOADER_STACK)
(new Exception("Just used to get stack trace")).printStackTrace();
long start = System.currentTimeMillis();
javaClass = Debugify.debugifyClass(javaClass, className);
long end = System.currentTimeMillis();
Debugger.timeDebugifying += (end - start);
bytes = javaClass.getBytes();
return bytes;
}
protected Class findClass(String className, boolean instrument) throws ClassNotFoundException {
JavaClass javaClass = null;
try {
javaClass = Repository.lookupClass(className);
} catch (ClassNotFoundException e) {
if (Debugger.TRACE_LOADER) e.printStackTrace();
throw e;//new RuntimeException(e);
}
Class clazz;
if (javaClass == null)
return null;
if (!Debugger.USE_BOOTCLASSLOADER) {
if (Debugger.TRACE_LOADER)
println(spacesExact() + "DebugifyingClassLoader debugifying: "
+ className);
if (Debugger.TRACE_LOADER_STACK)
(new Exception("Just used to get stack trace"))
.printStackTrace();
long start = System.currentTimeMillis();
javaClass = Debugify.debugifyClass(javaClass, className);
long end = System.currentTimeMillis();
Debugger.timeDebugifying += (end - start);
}
byte[] b = javaClass.getBytes();
clazz = defineClass(className, b, 0, b.length);
if (Debugger.TRACE_LOADER)
println(spacesMinus() + "DebugifyingClassLoader loaded: "
+ className);
return clazz;
}
}