I have a Lotus Notes database which is performing some interaction with a remote web service. I've written a custom Java class to perform the interaction.
The class methods can be executed from one of three locations depending on the user's setup:
Within my class I would simply like to be able to return the location the current class is executing from. So if it's executing from either option 2 or option 3, then return the JAR file path. If it's executing from option 1 then return something else which I can handle.
I've tried the following.
getClass().getProtectionDomain().getCodeSource().getLocation()
Which results in:
java.security.AccessControlException: Access denied (java.lang.RuntimePermission getProtectionDomain)
There is no option to change any security settings on any clients running this.
String myName = "/" + getClass().getName().replace('.', '/') + ".class";
URL myResourceURL = getClass().getResource(myName);
Result: myResourceURL is ALWAYS null.
String myName2 = getClass().getName().replace('.', '/') + ".class";
ClassLoader myCL = getClass().getClassLoader();
URL myResourceURL2 = myCL.getResource(myName);
Result: myResourceURL2 is ALWAYS null.
a) Where am I going wrong above?
and
b) how do I get the location of the currently executing class using a different method?
A JAR file may contain a manifest file, that is located at META-INF/MANIFEST. MF . The entries in the manifest file describe how to use the JAR file. For instance, a Classpath entry can be used to specify other JAR files to load with the JAR.
I have managed to overcome this by wrapping my code within a "AccessController.doPrivileged" block i.e:
final String[] myLocationViaProtectionDomain = {null};
AccessController.doPrivileged(new PrivilegedAction(){
public Object run(){
myLocationViaProtectionDomain[0] = getClass().getProtectionDomain().getCodeSource().getLocation().toString();
debug("myLocationViaProtectionDomain: " + myLocationViaProtectionDomain[0]);
return null;
}
});
Interestingly this approach works exactly as I want when the JAR file is located within the client's JVM directory i.e. points 2 and 3 from my original post. However when the same code runs when the code is being executed from within a Java script library, the following exception is thrown:
java.security.AccessControlException: Access denied (java.lang.RuntimePermission getProtectionDomain)
Which is fine because at least there is a differentiation there between 1 and (2 & 3) which I can then handle properly.
This solution was pointed out to me by the excellent Mikkel from lekkimworld.com (Twitter: @lekkim) so big thanks go out to him.
I am not sure if this helps, but we "switch" our user.dir
(System property) to make sure we run "out of" a certain directory for our application. In our case we have a web start application that we kick off through Lotus Notes (which calls a BAT file, which invokes Java Web Start (JAWS) ...)
But anyway, what we do is the following.
//Normally you don't ever want to do this......
Class clazz = ClassLoader.class;
Field field = clazz.getDeclaredField("sys_paths");
field.setAccessible(true);
field.setClass(clazz, null);
try {
//Basically we read in the path and then loop through and remove our current
//directory which is where we tend to "kick off from" rather than where we want
//to run from.
String minusCurrentDir = removeCurrentDirectoryFromPath(System.getProperty("java.library.path");
System.setProperty("java.library.path", minusCurrentDir);
}
finally {
field.setAccessible(true);
}
Now later on you can access and modify the user.dir
property or ask it where it is. This may give you access to what you want (?) Or at least maybe the top code can help.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With