OSGI: просить Framework загрузить класс, экспортируемый пакетом, не посещая загрузчик классов каждого пакета? - PullRequest
1 голос
/ 31 августа 2011

OK. Итак, у меня есть org.osgi.framework.launch.Framework, который я создал программным способом следующим образом.

framework = ServiceLoader.load(FrameworkFactory.class).iterator().next().newFramework(getFrameworkConfig());
framework.start();
installBundles(BUNDLES_PATH); // installs bundles from a directory, by searching BUNDLES_PATH recursively for JARs

То, что я хочу сделать, это иметь универсальный метод loadClass (как метод в этом классе), который будет сканировать установленные пакеты, читать их объявления Export-Package: и вызывать метод loadClass правильного пакета, основанный на packageName класса, который я передаю в качестве параметра.

Есть ли умный способ сделать это? или лучше просто сделать это:

Class<?> c = null;
// else try every installed bundle one-by-one
for (Bundle bundle : framework.getBundleContext().getBundles()) {
   try {
      c = bundle.loadClass(className);

   } catch (ClassNotFoundException e) {
      // OK, move onto next bundle
      continue;
   }
   if (c != null)
      break;
}
return c;

Я понимаю, что могу использовать сервисы, чтобы пакеты просто публиковали свои доступные сервисы, и чтобы инфраструктура запрашивала сервис с помощью getAllServiceReferences (), но это больше для программиста, и я не уверен, что хочу идти по пути Декларативные услуги.

1 Ответ

2 голосов
/ 31 августа 2011

Я бы предостерег от такого подхода.Платформа OSGi может содержать несколько поставщиков или версий пакета.Попытка создать единый загрузчик классов, который корректно справляется с этим, не тривиальна.Однако, если вы хотите запросить экспортируемые пакеты, у вас есть два варианта, в зависимости от того, какую версию OSGi вы используете.

Если вы используете OSGi до OSGi R4.3, вы можете использовать PackageAdmin .Это сервис, зарегистрированный в реестре сервисов, который позволяет вам запрашивать, какие пакеты экспортируются пакетами в платформе.Особый интерес для вас будет метод getExportedPackage .Это позволяет вам выбрать поставщика пакета, а затем вы можете вызвать loadClass для пакета, который предоставляет пакет.

PackageAdmin устарел в R4.3 (хотя Equinox все еще его реализует).Это сложнее.Чтобы делать то, что вы хотите, вам нужно использовать новый BundleWiring API.Это включает в себя получение каждого пакета в системе и выполнение следующих действий:

BundleWiring bw = bundle.adapt(BundleWiring.class);
List<BundleCapability> capabilities = bw.getCapabilities(BundleRevision.PACKAGE_NAMESPACE);
for (BundleCapability bc : capabilities) {
    String pkg = bc.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE);
}

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

...