This time I'm using a little introspection to try to catch evil code. Hopefully this check can't be circumvented, at least if a SecurityManager is in place, and also hopefully won't be stopped by any SecurityManager (it doesn't immediately seems so: one can use getClass() at any time, right? Can one also use the 1.5 getEnclosingClass() without being stopped?)
(If you use Eclipse, you can mark the entire code below (all classes in one go), Ctrl+C, then activate the project node of a project and hit Ctrl+V. You will probably have to organize imports afterwards).
package com.example;
import api.WantedCode;
public class NeedingCode {
// Driver
public static void main(String[] args) {
// .. we have an instance of this class
WantedCode code = new WantedCode();
// And access its package private method through a "friend-proxy"
FriendProxy.getProxy().invokeWantedMethodOf(code);
}
}
// ------------
package com.example;
import api.WantedCode;
public abstract class FriendProxy {
// :: Proxy interface method
public abstract void invokeWantedMethodOf(WantedCode instance);
// :: Friend infrastructure
private static FriendProxy _proxy;
public static void setProxy(FriendProxy proxy) {
// Verify that the origin of this proxy matches our expectations.
if (proxy.getClass().getEnclosingClass() != WantedCode.class) {
throw new IllegalAccessError("Only my friend can invoke this method.");
}
_proxy = proxy;
}
// :: Package-private accessor to get to friend's package private method.
static FriendProxy getProxy() {
return _proxy;
}
}
// ------------
package api;
import com.example.FriendProxy;
public class WantedCode {
void wantedMethod() {
System.out.println("Hi from the package-private method in the API!");
}
static {
FriendProxy.setProxy(new GivingAccessToNeedingCode());
}
private static class GivingAccessToNeedingCode extends FriendProxy {
@Override
public void invokeWantedMethodOf(WantedCode instance) {
instance.wantedMethod();
}
}
}
// ------------
package com.example;
import api.WantedCode;
/**
* Test whether the evilness is caught.
*/
public class EvilCode {
// Driver
public static void main(String[] args) {
WantedCode code = new WantedCode();
FriendProxy.setProxy(new FriendProxy() {
@Override
public void invokeWantedMethodOf(WantedCode instance) {
System.err.println("I'm evil!");
}
});
FriendProxy.getProxy().invokeWantedMethodOf(code);
}
}
6 comments: