我有一个Lotus Notes数据库,它正在与远程Web服务进行一些交互。我编写了一个自定义Java类来执行交互。
根据用户的设置,可以从三个位置之一执行类方法:
在我的课程中,我只想返回当前正在执行的课程的位置。因此,如果它从选项2或选项3执行,则返回JAR文件路径。如果它从选项1执行,则返回我可以处理的其他内容。
我尝试了以下内容。
getClass().getProtectionDomain().getCodeSource().getLocation()
结果是:
java.security.AccessControlException: Access denied (java.lang.RuntimePermission getProtectionDomain)
在运行此功能的任何客户端上都无法更改任何安全设置。
String myName = "/" + getClass().getName().replace('.', '/') + ".class";
URL myResourceURL = getClass().getResource(myName);
结果: myResourceURL始终为空。
String myName2 = getClass().getName().replace('.', '/') + ".class";
ClassLoader myCL = getClass().getClassLoader();
URL myResourceURL2 = myCL.getResource(myName);
结果: myResourceURL2始终为空。
a)我上面哪里出错了?
和
b)如何使用不同的方法获取当前正在执行的类的位置?
答案 0 :(得分:4)
我设法通过将代码包装在“AccessController.doPrivileged”块中来克服这个问题,即:
final String[] myLocationViaProtectionDomain = {null};
AccessController.doPrivileged(new PrivilegedAction(){
public Object run(){
myLocationViaProtectionDomain[0] = getClass().getProtectionDomain().getCodeSource().getLocation().toString();
debug("myLocationViaProtectionDomain: " + myLocationViaProtectionDomain[0]);
return null;
}
});
有趣的是,当JAR文件位于客户端的JVM目录中时,即原始帖子中的第2点和第3点,此方法完全符合我的要求。但是,当从Java脚本库中执行代码时运行相同的代码时,将引发以下异常:
java.security.AccessControlException: Access denied (java.lang.RuntimePermission getProtectionDomain)
这很好,因为至少在1和(2&3)之间有区别,然后我可以正确处理。
来自lekkimworld.com(Twitter:@lekkim)的优秀Mikkel向我指出了这个解决方案,非常感谢他。
答案 1 :(得分:1)
我不确定这是否有帮助,但我们“切换”我们的user.dir
(系统属性)以确保我们为我们的应用程序运行“某个目录”。在我们的例子中,我们有一个Web启动应用程序,我们通过Lotus Notes启动它(调用BAT文件,调用Java Web Start(JAWS)......)
但无论如何,我们所做的就是以下几点。
//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);
}
稍后,您可以访问和修改user.dir
属性或询问它的位置。这可以让您访问所需的内容(?)或者至少顶级代码可以提供帮助。
答案 2 :(得分:0)
您的最后一行代码有myCL.getResouce(myName)
,代之以myName2
。这可能会导致问题。如果它使用带有前导'/'的名称版本,那么您将无法从ClassLoader.getResource()调用中获得任何内容。它必须没有领先的斜线。如果这没有帮助,您也可以尝试:
ClassLoader.getSystemResource(myName2); // name without leading slash
如果仍然无效,则可能是安全问题。根据{{3}},如果“调用者没有足够的权限获取资源”,它可以返回null。我只知道Java,而不是Lotus,所以我不知道它运行代码的安全环境是什么类型。