как определить, выполняется ли в контейнере osgi

#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;
}