当前运行的类或JAR文件的位置

我有一个Lotus Notes数据库,它正在与远程Web服务进行一些交互。 我编写了一个自定义Java类来执行交互。

可以根据用户的设置从三个位置之一执行类方法:

  1. 在通过Lotus Notes Java代理调用的Java脚本库中
  2. 在位于用户的“jvm / lib / ext”目录中的JAR文件中
  3. 在位于用户“jvm / lib”目录中的自定义目录中的JAR文件中(例如,“jvm / lib / custom_dir”)。 Lotus Notes JVM通过使用“JavaUserClassesExt”本地notes.ini变量来了解自定义目录。

在我的课程中,我希望能够返回当前类正在执行的位置。 因此,如果它从选项2或选项3执行,则返回JAR文件路径。 如果它从选项1执行,则返回我可以处理的其他内容。

我尝试了以下内容。

getProtectionDomain()方法

getClass().getProtectionDomain().getCodeSource().getLocation() 

结果如下:

 java.security.AccessControlException: Access denied (java.lang.RuntimePermission getProtectionDomain) 

没有选项可以更改运行此任何客户端的任何安全设置。

Class.getResource方法

 String myName = "/" + getClass().getName().replace('.', '/') + ".class"; URL myResourceURL = getClass().getResource(myName); 

结果: myResourceURL始终为null。

ClassLoader.getResource方法

 String myName2 = getClass().getName().replace('.', '/') + ".class"; ClassLoader myCL = getClass().getClassLoader(); URL myResourceURL2 = myCL.getResource(myName); 

结果: myResourceURL2始终为null。

a)我上面哪里出错了?

b)如何使用不同的方法获取当前正在执行的类的位置?

我已经设法通过将我的代码包装在“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目录中时,即原始post中的第2点和第3点,这种方法完全符合我的要求。 但是,当在Java脚本库中执行代码时运行相同的代码时,会引发以下exception:

 java.security.AccessControlException: Access denied (java.lang.RuntimePermission getProtectionDomain) 

这很好,因为至少在1和(2和3)之间存在区别,然后我可以正确处理。

来自lekkimworld.com(Twitter:@lekkim)的优秀Mikkel向我指出了这个解决方案,非常感谢他。

我不确定这是否有帮助,但我们“切换”我们的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属性或询问它的位置。 这可以让您访问所需的内容(?)或者至少顶级代码可以提供帮助。

你的最后一行代码有myCL.getResouce(myName) ,它应该使用myName2 。 这可能会导致问题。 如果它使用带有前导’/’的名称版本,那么您将无法从ClassLoader.getResource()调用中获得任何内容。 它必须没有前导斜线。 如果这没有帮助,你也可以尝试:

 ClassLoader.getSystemResource(myName2); // name without leading slash 

如果仍然无效,则可能是安全问题。 根据ClassLoader.getResource()文档 ,如果“调用者没有足够的权限来获取资源”,它可以返回null。 我只知道Java,而不是Lotus,所以我不知道它运行代码的安全环境是什么。