106 lines
3.2 KiB
Java
106 lines
3.2 KiB
Java
import java.io.*;
|
|
import org.apache.bcel.*;
|
|
import org.apache.bcel.classfile.*;
|
|
import org.apache.bcel.generic.*;
|
|
|
|
/**
|
|
* Adds "entering" logs to all methods of a class that have the LogEntry annotation.
|
|
* @version 1.10 2007-10-27
|
|
* @author Cay Horstmann
|
|
*/
|
|
public class EntryLogger
|
|
{
|
|
/**
|
|
* Adds entry logging code to the given class
|
|
* @param args the name of the class file to patch
|
|
*/
|
|
public static void main(String[] args)
|
|
{
|
|
try
|
|
{
|
|
if (args.length == 0) System.out.println("USAGE: java EntryLogger classname");
|
|
else
|
|
{
|
|
JavaClass jc = Repository.lookupClass(args[0]);
|
|
ClassGen cg = new ClassGen(jc);
|
|
EntryLogger el = new EntryLogger(cg);
|
|
el.convert();
|
|
File f = new File(Repository.lookupClassFile(cg.getClassName()).getPath());
|
|
cg.getJavaClass().dump(f.getPath());
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Constructs an EntryLogger that inserts logging into annotated methods of a given class
|
|
* @param cg the class
|
|
*/
|
|
public EntryLogger(ClassGen cg)
|
|
{
|
|
this.cg = cg;
|
|
cpg = cg.getConstantPool();
|
|
}
|
|
|
|
/**
|
|
* converts the class by inserting the logging calls.
|
|
*/
|
|
public void convert() throws IOException
|
|
{
|
|
for (Method m : cg.getMethods())
|
|
{
|
|
AnnotationEntry[] annotations = m.getAnnotationEntries();
|
|
for (AnnotationEntry a : annotations)
|
|
{
|
|
if (a.getAnnotationType().equals("LLogEntry;"))
|
|
{
|
|
for (ElementValuePair p : a.getElementValuePairs())
|
|
{
|
|
if (p.getNameString().equals("logger"))
|
|
{
|
|
String loggerName = p.getValue().stringifyValue();
|
|
cg.replaceMethod(m, insertLogEntry(m, loggerName));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Adds an "entering" call to the beginning of a method.
|
|
* @param m the method
|
|
* @param loggerName the name of the logger to call
|
|
*/
|
|
private Method insertLogEntry(Method m, String loggerName)
|
|
{
|
|
MethodGen mg = new MethodGen(m, cg.getClassName(), cpg);
|
|
String className = cg.getClassName();
|
|
String methodName = mg.getMethod().getName();
|
|
System.out.printf("Adding logging instructions to %s.%s%n", className, methodName);
|
|
|
|
int getLoggerIndex = cpg.addMethodref("java.util.logging.Logger", "getLogger",
|
|
"(Ljava/lang/String;)Ljava/util/logging/Logger;");
|
|
int enteringIndex = cpg.addMethodref("java.util.logging.Logger", "entering",
|
|
"(Ljava/lang/String;Ljava/lang/String;)V");
|
|
|
|
InstructionList il = mg.getInstructionList();
|
|
InstructionList patch = new InstructionList();
|
|
patch.append(new PUSH(cpg, loggerName));
|
|
patch.append(new INVOKESTATIC(getLoggerIndex));
|
|
patch.append(new PUSH(cpg, className));
|
|
patch.append(new PUSH(cpg, methodName));
|
|
patch.append(new INVOKEVIRTUAL(enteringIndex));
|
|
InstructionHandle[] ihs = il.getInstructionHandles();
|
|
il.insert(ihs[0], patch);
|
|
|
|
mg.setMaxStack();
|
|
return mg.getMethod();
|
|
}
|
|
|
|
private ClassGen cg;
|
|
private ConstantPoolGen cpg;
|
|
} |