You can trace the origin of a method call using a custom SecurityManager class
In the process of debugging a Java program, at times you have probably found yourself wishing that a method could figure out the class that was calling it. When designing a class, right from the start you may have wanted this capability. But getting this wish would violate the OO principle that an object does not depend on what calls it. Still, if you are trying to track down faulty method calls in a large program, adding some debugging code to find the offending object could help.
The SecurityManager class contains a handy method that returns the class context of the current method call. In other words, it gives you an array of Class objects that represent the classes involved in making the current method call. For example, if Foo invoked a method in Bar, and Bar invoked a Baz, the class context for the method call in Baz would contain Baz, Bar, and Foo, in that order. The most recent class is always the first class in the list. The name of this method is getClassContext.
Unfortunately, with getClassContext thereโs one hangup: Itโs a protected method. However, you can violate another OO principle by exposing a protected method through a subclass. The following DummySM class does just this:
public class DummySM extends SecurityManager
{ public Class[] context()
{ return getClassContext(); }
}
Now a method that wants to see what classes have called it can use the context method. The ShowCaller object prints the entire class context for the callme method. It checks first to see if DummySM is being used as the SecurityManager class.
public class ShowCaller extends Object
{ public ShowCaller() { }
public void callme() {
// Get the current security manager SecurityManager sm =
System.getSecurityManager();
// Make sure the security manager is a DummySM
if (sm instanceof DummySM) {
DummySM dummy = (DummySM) sm;
// Get the class context
Class classes[] = dummy.context();
// Print the context
System.out.println("Callme context:");
for (int i=0; i < classes.length; i++) {
System.out.println(classes[i]);
}
}
}
}
Following is a pair of dummy classes used for testing ShowCaller.java. Given a ShowCaller object, these objects invoke the callme method in ShowCaller.
public class FooCaller extends Object
{ ShowCaller caller;
public FooCaller(ShowCaller caller)
{ this.caller = caller; }
public void callme()
{ caller.callme(); }
}
public class BarCaller extends Object
{ ShowCaller caller;
public BarCaller(ShowCaller caller)
{ this.caller = caller; }
public void callme()
{ caller.callme(); }
}
Finally, here is a test program to demonstrate this:
public class TestContext extends Object
{ public static void main(String[] args) {
// Set DummySM as the security manager for this program
System.setSecurityManager(new DummySM());
ShowCaller sc = new ShowCaller();
FooCaller foo = new FooCaller(sc);
BarCaller bar = new BarCaller(sc);
foo.callme();
bar.callme(); }
}
This debugging technique is useful only for standalone applications because you are not allowed to override the security manager for an applet. A note of caution: If you end up using this mechanism as part of your actual class design, you should seriously reconsider your design. During normal operation, an object should not have to know what is invoking it.


