Как получить имя JAR, из которого запускается настольное приложение? - PullRequest
1 голос
/ 06 ноября 2010

Я создал простую библиотеку AppInfo , обеспечивающую простой способ отображения всегда действительной, автоматически обновляемой информации о версии запущенного программного обеспечения в приложениях Java, что особенно полезно в сочетании с автоматическими сборками с сервера CI.

В моей библиотеке необходимо прочитать MANIFEST.MF из JAR (в случае настольного приложения), из которого запускается конечное приложение (а не из любого другого пути к классам). В настоящее время я использую решение, основанное на идее, взятой с форума Sun (ссылка на которую больше не работает):

String classContainer = classFromRightJar.getProtectionDomain().getCodeSource().getLocation().toString();
URL manifestUrl = new URL("jar:" + classContainer + "!/META-INF/MANIFEST.MF");

и это обычно работает, но заставляет разработчика настольного приложения создавать дополнительный компонент, настроенный с именем класса, который находится в конкретном JAR.

Есть ли лучшее / универсальное решение, которое дает имя / местоположение / MANIFEST.MF из / из JAR, из которого запускается настольное приложение?

Спасибо за вашу помощь
Marcin

Ответы [ 2 ]

2 голосов
/ 11 февраля 2012

Системное свойство "sun.java.command" содержит имя jar-файла или имя класса, а также все аргументы метода main ().Так что для вызова

java -jar test.jar arg1 arg2

вы получите «test.jar arg1 arg2», а для

java test.Test arg1 arg2

значением свойства будет «test.Test arg1 arg2».Как следует из названия свойства, оно не является «официальным» (не должно работать с реализациями, отличными от Sun / Oracle).Я проверял это на Java 7, не знаю, когда он был представлен.

0 голосов
/ 07 ноября 2010

Под словом «вынуждает разработчика настольного приложения создавать дополнительные компоненты ...», вы имеете в виду, что вы не хотите, чтобы они вообще когда-либо ссылались на имена классов своих приложений? Если это так, то, вероятно, не существует надежного способа сделать это на 100%, но одним из подходов может быть вызов java.awt.Frame.getFrames () и проверка не-java * подклассов JFrame. E.g.:

for (Frame frame in Frame.getFrames()) {
    if (frame.getClass().getPackage().getName().startsWith("java"))
        continue;
    URL manifestURL = frame.getClass().getResource("/META-INF/MANIFEST.MF");
    // do something with the manifest
}

Это сломается, если приложение не подклассирует JFrame / Frame самостоятельно, поэтому вы также можете пройтись по дочерним элементам фрейма, чтобы также проверить подклассы дочерних элементов.

Другой подход может заключаться в том, чтобы захватить Thread.getAllStackTraces () и пройти по всем из них (особенно по «основному» потоку) в поисках основного класса, запустившего приложение, а затем получить манифест для этого класса.

Как я уже сказал, вероятно, не существует 100% надежного способа сделать это, так как приложение может не использовать никаких пользовательских подклассов, а стеки для потоков могут иметь смесь различных приложений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...