package test;
import java.util.StringTokenizer;
import alt.jiapi.event.MethodEventProducer;
import alt.jiapi.event.MethodListener;
import alt.jiapi.event.MethodEvent;
import alt.jiapi.*;
import alt.jiapi.util.Bootstrapper;
/**
* This class is mainly used to test Jiapi event model.
* In addition to that, it servers as an example of using
* Jiapi event model.<p>
* There is a not so obvious bug in this example/test.
*
* While this example traces method entries and exits, it failes
* on exceptions. That is, Exception is not considered method exit,
* and indentation of output is not correct if method leaves through
* an Exception.<p>
* This will be corrected as soon as we have a suitable instrumentor.
*/
public class CallTrace implements MethodListener {
private String prefix = System.getProperty("prefix", "");
private static String resolution = System.getProperty("resolution", "*");
/**
* Entry point.<br>
* Following System properties may be used to tune this utility.
* <ul>
* <li>include - ':' separated list of inclusion rules. Mandatory.
* <li>exclude - ':' separated list of exclusion rules. Optional.
* <li>resolution - Method resolution, like 'get*'
* <li>prefix - Prefix that gets printed on each event. Optional.
* This is useful for tracing software, that prints into
* System.out. One may use tools like grep, to filter console
* to show only events.
* </ul>
*/
public static void main(String [] args) throws Exception {
// Create context using provider of our choice
InstrumentationContext ctx =
new InstrumentationContext();
// Create Descriptor. No need to to add Instrumentors or
// Patches, since MethodEventProducer below will do it
// for our convenience. Behind the scenes.
InstrumentationDescriptor id = new InstrumentationDescriptor();
String inclusions = System.getProperty("include");
if (inclusions != null) {
StringTokenizer st = new StringTokenizer(inclusions, ":");
while (st.hasMoreTokens()) {
id.addInclusionRule(st.nextToken());
}
}
else {
usage();
System.exit(1);
}
String exclusions = System.getProperty("exclude");
if (exclusions != null) {
StringTokenizer st = new StringTokenizer(exclusions, ":");
while (st.hasMoreTokens()) {
id.addExclusionRule (st.nextToken());
}
}
// Store Descriptor to Context
ctx.addInstrumentationDescriptor(id);
// This will provide Instrumentors and Patches needed in this
// test/sample
MethodEventProducer mep = new MethodEventProducer(id, resolution);
// Add MethodEventListner ----
CallTrace et = new CallTrace();
mep.addMethodListener(et);
// The first argument is class name, the rest are String args.
String [] _args = new String[args.length - 1];
System.arraycopy(args, 1, _args, 0, _args.length);
Bootstrapper.launch(args[0], _args, ctx, CallTrace.class.getClassLoader());
}
int eventCount = 0;
public void methodEntered (MethodEvent event) {
System.out.println(prefix + eventCount++ + ":" + indentation +
event.getClassName() + "." + event.getMethodName());
indentation = indentMore();
}
public void methodExited (MethodEvent event) {
indentation = indentLess();
}
String indentation = "";
private String indentMore() {
return indentation + " ";
}
private String indentLess() {
if (indentation.length() < 3) {
return "";
}
return indentation.substring(0, indentation.length() - 3);
}
private static void usage() {
System.out.println("usage : ");
System.out.println(" java -Dinclude=foo.*:bar.* [-Dexclude=foobar.*] test.CallTrace test.Foo");
}
}