问题 如何在执行java.io.File或FileInputStream时引用OSGi包中的包含文件


我正在使用aQute Bnd工具集来创建一个OSGi包,并打包了一些相关的“资源”文件。这包括我创建的资源目录中的* .css文件和* .xsd文件。

我在下面列出了以下内容 bundle.bnd 文件:

Include-Resource: resources/=resources/ 

当我进行构建时,生成的* .jar文件在jar包文件的顶级目录的resources目录中包含* .css和* .xsd文件。

但是,在实际代码中,我很难尝试将其作为类路径的一部分引用:

我尝试过以下方法:

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(我们用于部署)时遇到此错误。注意我试图在BundleActivator之外的Java类中执行此操作。

我是否需要始终参考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引用,而这些引用似乎并不优雅。

有没有办法在bundle / .jar文件的任何给定Java类中引用bundle jar文件中包含的'resources'目录的路径?如果它涉及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");


3247
2017-09-28 06:45


起源



答案:


捆绑接口 有一个 getEntry(java.lang.String path) 返回Url的方法,记录为:

返回此捆绑包中指定路径的条目的URL。此捆绑包的类加载器不用于搜索条目。仅搜索此包的内容以查找该条目。 指定的路径始终相对于此捆绑包的根目录,可以以“/”开头。路径值“/”表示此捆绑包的根。


9
2017-09-28 07:20



无论如何在BundleActivator的上下文之外访问它?我猜你指的是这样做:public void start(BundleContext context){Bundle bundle = context.getBundle(); InputStream in = bundle.getEntry(“/ resource / example.css”)。openStream(); }。但是,我正在寻找一个解决方案(如果有的话)在BundleActivator之外访问它。我看了看 eclipsezone.com/eclipse/forums/t101557.html 但我仍然感到困惑 - herbyme
你有没有想过从bundle id获取Bundle对象的方法? - Manuel Selva
我可以得到这个条目,但问题是getEntry()只提供相对路径,而不是bundle的完整(根)路径: techinfopad.com/spring/...。 - herbyme


答案:


捆绑接口 有一个 getEntry(java.lang.String path) 返回Url的方法,记录为:

返回此捆绑包中指定路径的条目的URL。此捆绑包的类加载器不用于搜索条目。仅搜索此包的内容以查找该条目。 指定的路径始终相对于此捆绑包的根目录,可以以“/”开头。路径值“/”表示此捆绑包的根。


9
2017-09-28 07:20



无论如何在BundleActivator的上下文之外访问它?我猜你指的是这样做:public void start(BundleContext context){Bundle bundle = context.getBundle(); InputStream in = bundle.getEntry(“/ resource / example.css”)。openStream(); }。但是,我正在寻找一个解决方案(如果有的话)在BundleActivator之外访问它。我看了看 eclipsezone.com/eclipse/forums/t101557.html 但我仍然感到困惑 - herbyme
你有没有想过从bundle id获取Bundle对象的方法? - Manuel Selva
我可以得到这个条目,但问题是getEntry()只提供相对路径,而不是bundle的完整(根)路径: techinfopad.com/spring/...。 - herbyme


我认为答案应该简单如下:

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

即确保路径中有一个前导斜杠。你没有一个前导斜杠,这会使它与你正在调用的类“相对”。

或者,以下应该起作用:

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

3
2017-10-02 14:37



我选择了此解决方案,但在尝试导入所有目录的值时存在问题,例如我正在使用BluePrint CSS并且遇到了this.getClass()。getClassLoader()。getResource(“resources / css”)的问题,因为不仅有很多文件,还有子目录。我最终将文件“复制”到临时位置,但这会导致一些性能问题。 - herbyme


如果您使用Eclipse / Equinox构建,那么您可以通过调用类似于以下内容的BundleActivator中的BundleContext来获取Bundle的位置:

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

Platform和FileLocator类来自org.eclipse.core.runtime插件,因此如果您依赖于该插件,那么上面的内容应该允许您访问您的资源。


2
2017-09-28 10:08



我试图避免使用org.eclipse.core.runtime插件作为我们的部署,决定使用Apache Felix(除非有一种方法可以合并它)。如果我在Eclipse运行时环境下运行它,则上述工作正常。 - herbyme