As others have mentioned, using the stack trace is one way to implement the functionality that you are looking for. Generally, if one needs to "block" callers from a public method, it could be a sign of poor design. As a rule of thumb, use access modifiers that restrict the scope as much as possible. However, making a method package-private or protected is not always an option. Sometimes, one may want to group some classes in a separate package. In that case, the default (package-private) access is too restrictive, and it usually does not make sense to subclass, so protected is not helpful either.
If restricting calling to certain classes is desired, you can create a method like:
public static void checkPermission(Class... expectedCallerClasses) {
StackTraceElement callerTrace = Thread.currentThread().getStackTrace()[3];
for (Class expectedClass : expectedCallerClasses) {
if (callerTrace.getClassName().equals(expectedClass.getName())) {
return;
}
}
throw new RuntimeException("Bad caller.");
}
Using it is very simple: just specify what class(es) can call the method. For example,
public void stop() {
checkPermission(ShutdownHandler.class);
running = false;
}
So, if the stop method gets called by a class other than ShutdownHandler, checkPermission will throw an IllegalStateException.
You may wonder why checkPermission is hard-coded to use the fourth element of the stack trace. This is because Thread#getStackTrace() makes the most recently called method the first element. So,
getStackTrace()[0] would be the call to getStackTrace itself.
getStackTrace()[1] would be the call to checkPermission.
getStackTrace()[2] would be the call to stop.
getStackTrace()[3] would be the method that called stop. This is what we are interested in.
You mentioned that you want methods to be called from a specific class and method, but checkPermission only checks for class names. Adding the functionality to check for method names requires only a few modifications, so I'm going to leave that as an exercise.