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

时间:2011-07-13 09:04:55

标签: java jar lotus-notes

我有一个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变量来了解自定义目录。
  4. 在我的课程中,我只想返回当前正在执行的课程的位置。因此,如果它从选项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始终为空。

    ClassLoader.getResource方法

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

    结果: myResourceURL2始终为空。

    a)我上面哪里出错了?

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

3 个答案:

答案 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,所以我不知道它运行代码的安全环境是什么类型。