#java #eclipse #osgi
#java #eclipse #osgi
Вопрос:
У меня есть пакет OSGi, который также может выполняться в обычном процессе Java. Мне нужно иметь возможность определить, был ли пакет загружен в систему OSGi или нет. Как я могу это сделать? Если нет стандартного для OSGi способа сделать это, я соглашусь на подход, специфичный для Eclipse / Equinox.
Ответ №1:
Добавьте Bundle-Activator в свой MANIFEST.MF. Если он создается, значит, ваш JAR запущен в контейнере OSGi.
Комментарии:
1. Здесь много голосов. Кто-нибудь может объяснить, почему новичкам?
2. Это простое решение, которое работает. До OSGi 4.2 не было удобного способа проанализировать загрузчик классов, чтобы определить его статус как пакета (PackageAdmin.getBundle — единственный способ).
3. Спасибо. Этот комментарий в скобках — это (действенная) деталь, которая, я думаю, мне нужна.
4. Ну, чтобы получить доступ к PackageAdmin, вам нужно каким-то образом получить BundleContext для GetService, поэтому вам где-то нужен активатор пакета. Если у вас уже есть активатор пакета в каком-либо другом JAR, тогда да, вы можете использовать PackageAdmin.getBundle для проверки произвольных классов.
5. Активатор пакета требует реализации org.osgi.framework. BundleActivator, которого нет в среде, отличной от osgi.
Ответ №2:
Если у вас нет активатора, вы также можете попробовать запросить свой пакет:
Bundle b = org.osgi.framework.FrameworkUtil.getBundle(MyClass.this);
Если он возвращает null, ваш класс не был загружен OSGi.
Комментарии:
1. Как это соотносится с «getClass().getClassLoader() instanceof org.osgi.framework. Подход «BundleReference»? Будет ли это работать в более широком диапазоне версий OSGi?
2. Если взглянуть на реализацию, она также зависит от BundleReference и доступна с OSGi 4.2 (eclipse 3.5.x?). Я бы рекомендовал это вместо проверки instanceof, потому что это API.
3. Обратите внимание, что проверка «instanceof» также является API, поскольку в спецификации указано, что загрузчик классов пакета должен реализовывать BundleReference.
4. Разве это не вызвало бы исключение class not found, если бы этот код выполнялся в среде выполнения, отличной от osgi?
Ответ №3:
Вы можете проверить, является ли «this.getClass().getClassLoader() экземпляром org.osgi.framework.BundleReference», которое должно быть истинным, только если вы работаете в среде OSGi R4.2.
Комментарии:
1. Я работал с тестами в настройке eclipse и получил org.eclipse.osgi в качестве начала пакета загрузчика классов. Я решил проверить, каково имя загрузчика классов в ситуации, отличной от osgi (com.sun…. Я забыл, теперь я дома). Это оставляет мой тест открытым для работы в других реализациях OSGI, хотя он зависит от использования других реализаций загрузчика классов, отличных от osgi, и вносит свой вклад в работу.
Ответ №4:
Улучшенный ответ Ричарду С. Холлу, который не требует зависимости от osgi при компиляции и во время выполнения. Он также проверяет, реализует ли загрузчик классов класса org.osgi.framework.BundleReference
интерфейс.
Class<?> classToCheck = this.getClass().getClassLoader().getClass();
boolean runningOsgi = isOsgiClassLoader(classToCheck);
...
boolean isOsgiClassLoader(Class<?> classLoaderClass) {
Class<?> c = classLoaderClass;
while (c != null) {
if (c.getName().equals("org.osgi.framework.BundleReference")) {
return true;
}
for (Class<?> ifc : c.getInterfaces()) {
if (isOsgiClassLoader(ifc)) {
return true;
}
}
c = c.getSuperclass();
}
return false;
}