Расположение текущего запущенного класса или файла JAR - PullRequest
10 голосов
/ 13 июля 2011

У меня есть Lotus Notes база данных, которая выполняет некоторое взаимодействие с удаленным веб-сервисом.Я написал собственный класс Java для выполнения взаимодействия.

Методы класса могут выполняться из одного из трех мест в зависимости от настроек пользователя:

  1. В библиотеке сценариев Javaвызывается через Java-агент Lotus Notes
  2. В файле JAR, расположенном в пользовательском каталоге "jvm / lib / ext"
  3. В файле JAR, расположенном в пользовательском каталоге внутри пользовательского каталога "jvm /"каталог lib "(например," jvm / lib / custom_dir ").Lotus Notes JVM знает о пользовательском каталоге через использование локальной переменной notes.ini "JavaUserClassesExt".

В моем классе я просто хотел бы иметь возможность вернуть местоположение, в котором находится текущий класс.выполняется из.Так что, если он выполняется из опции 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 ]

4 голосов
/ 20 июля 2011

Мне удалось преодолеть это, поместив мой код в блок «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), поэтому ему огромное спасибо.

1 голос
/ 20 июля 2011

Я не уверен, поможет ли это, но мы «переключаем» наше user.dir (системное свойство), чтобы убедиться, что мы «исчерпали» определенный каталог для нашего приложения. В нашем случае у нас есть веб-приложение запуска, которое мы запускаем через 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 и изменить его или спросить, где оно находится. Это может дать вам доступ к тому, что вы хотите (?) Или, по крайней мере, может помочь верхний код.

0 голосов
/ 16 июля 2011

Ваша последняя строка кода имеет myCL.getResouce(myName), где вместо нее следует использовать myName2.Это может быть причиной проблемы.Если он использует версию имени с начальным '/', то вы ничего не получите от вызова ClassLoader.getResource ().Он не должен иметь косой черты.Если это не поможет, вы также можете попробовать:

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

Если это по-прежнему не работает, это может быть проблемой безопасности.Согласно ClassLoader.getResource () docs , он может возвращать ноль, если «у вызывающего нет достаточных привилегий для получения ресурса».Я просто знаю Java, а не Lotus, поэтому я не знаю, в какой среде безопасности он запускает код.

...