Как ссылаться на включенный файл в комплекте OSGi при выполнении java.io.File или FileInputStream

Я использую набор инструментов aQute Bnd для создания пакета OSGi и упакован с некоторыми зависимыми файлами ресурсов. Это включает файлы *.css и *.xsd в каталоге ресурсов, который я создал.

Я включил следующее в файл bundle.bnd:

Include-Resource: resources/=resources/ 

и когда я делаю сборку, сгенерированный файл *.jar имеет файлы *.css и *.xsd в каталоге ресурсов в верхней папке файла пакета jar.

Однако в фактическом коде мне трудно найти ссылку на это как часть моего пути к классу:

Я пробовал следующее:

new File("resources/example.css");

Я также пробовал:

URL cssFile = this.getClass().getResource("resources/example.css");
try
{
   file = new File(cssFile.toURI()));
}
catch(Exception e)
{
   e.printStackTrace();  
}

Я либо получаю ошибку NullPointException, либо файл не может быть найден Ошибка IOException (в зависимости от того, какой я использую). Я получаю эту ошибку при запуске как в Eclipse Equinox в режиме настройки отладки, так и в Apache Felix (который мы используем для нашего развертывания). Примечание. Я пытаюсь сделать это в Java-классах за пределами BundleActivator.

Нужно ли всегда ссылаться на контекст BundleActivator, например?

 /*
 * (non-Javadoc)
 * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
 */
 @Override
 public void start(BundleContext context) throws Exception 
 {   
     /* Service to host the Bundle interface. */
     ServletContainerService service = new ServletContainerService();
     service.addServlet(new ServletContainer(new AxisServlet(), true));
     this.serverReg = context.registerService(ServletContainerService.class.getName(), service, null);

     cssFile = new File(context.getClass.getResource("resource/example.css")); 
 }

Я думаю, что вышеупомянутое будет работать, но будет означать, что мне придется передать ссылку cssFile, вокруг которой не кажется элегантным.

Есть ли способ ссылаться на путь каталога ресурсов, который включен в файл jar bundle в любом заданном Java-классе, который является частью файла bundle/.jar? Если это связано с BundleContext, есть ли способ ссылаться на него в любом классе Java?

Любая помощь будет очень оценена.


Я посмотрел и Включая дополнительные ресурсы с пакетами OSGi, но кажется, что вам нужен BundleContext.

Возможно, я нашел возможное решение: http://www.vogella.de/blog/tag/plugin/

Похож, что у Vogella есть код для примера:

URL url;
try {
        url = new URL("platform:/plugin/de.vogella.rcp.plugin.filereader/files/test.txt");
    InputStream inputStream = url.openConnection().getInputStream();
    BufferedReader in = new BufferedReader(new InputStreamReader(inputStream));
    String inputLine;

    while ((inputLine = in.readLine()) != null) {
        System.out.println(inputLine);
    }

    in.close();

} catch (IOException e) {
    e.printStackTrace();
}

Кто-нибудь знает, является ли этот путь одинаковым, если он не является плагином, и если я использую разные среды OSGi, например. Equinox Eclipse против Apache Felix? например url = new URL("platform:/plugin/de.vogella.rcp.plugin.filereader/files/test.txt");

Ответ 1

Интерфейс Bundle имеет метод getEntry(java.lang.String path) которые возвращают Url и документируются как:

Возвращает URL-адрес для записи по указанному пути в этом пакете. Этот загрузчик классов пакетов не используется для поиска записи. Только содержимое этого пакета ищет запись. Указанный путь всегда относится к корню этого пучка и может начинаться с "/". Значение пути "/" указывает корень этого пакета.

Ответ 2

Я думаю, что ответ должен быть таким простым, как следующее:

URL cssFile = this.getClass().getResource("/resources/example.css");

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

В качестве альтернативы должно работать следующее:

this.getClass().getClassLoader().getResource("resources/example.css");

Ответ 3

Если вы создаете Eclipse/Equinox, вы можете получить местоположение Bundle из-за BundleContext, содержащегося в BundleActivator, вызывая что-то вроде:

Bundle yourBundle = Platform.getBundle("bundleSymbolicName");
Path relativePathToBundle = new Path("/relativePath");
FileLocator.openStream(yourBundle, relativePathToBundle, false); 

Классы платформы и FileLocator берутся из подключаемого модуля org.eclipse.core.runtime, поэтому, если у вас есть зависимость от этого, то вышеуказанное должно позволить вам получить доступ к вашему ресурсу.