How to reference an included file in OSGi bundle w

2020-02-28 03:52发布

问题:

I am using the aQute Bnd toolset to create an OSGi bundle and have packaged with some dependant 'resource' files. This includes *.css files and *.xsd files in a resources directory I have created.

I have included the following in the bundle.bnd file:

Include-Resource: resources/=resources/ 

and when I do a build, the generated *.jar file has the *.css and *.xsd files in the resources directory in the top directory of the jar bundle file.

However, in the actual code I am having difficulty in trying to refer to this as part of my class path:

I have tried the following:

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

I have also tried:

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

I either get a NullPointException error or a File cannot be found IOException error (depending which one I use). I get this error when running in both Eclipse Equinox in Debug Configuration mode as well as Apache Felix (which we are using for our deployment). Note I am trying to do this in Java classes outside of the BundleActivator.

Do I need to always refer to the context of the BundleActivator e.g.?

 /*
 * (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")); 
 }

I think the above will work, but will mean I will have to pass the cssFile reference around which does not appear to be elegant.

Is there any way to refer to the path of the 'resources' directory that is included in the bundle jar file in any given Java class that is part of the bundle/.jar file? If it involves the BundleContext, is there any way to reference this in any Java class?

Any help will be much appreciated.


I have had a look at and Including additional resources with OSGi bundles but it appears that you need the BundleContext.

I might have found a possible solution to this: http://www.vogella.de/blog/tag/plugin/

Looks like Vogella has some example code for this:

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();
}

Does anyone know if this path is the same if it isn't a plugin and if I am using different OSGi environments eg. Equinox Eclipse vs. Apache Felix? e.g. url = new URL("platform:/plugin/de.vogella.rcp.plugin.filereader/files/test.txt");

回答1:

The Bundle interface has a getEntry(java.lang.String path) method which return an Url and is documented as:

Returns a URL to the entry at the specified path in this bundle. This bundle's class loader is not used to search for the entry. Only the contents of this bundle are searched for the entry. The specified path is always relative to the root of this bundle and may begin with "/". A path value of "/" indicates the root of this bundle.



回答2:

I think the answer should be as simple as the following:

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

I.e. make sure there is a leading slash in the path. You had it without a leading slash, which would make it "relative" to the class you're calling from.

Alternatively the following should work:

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


回答3:

If you are building with Eclipse/Equinox, then you can get the location of a Bundle from outwith the BundleContext contained within the BundleActivator by calling something like:

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

The Platform and FileLocator classes come from the org.eclipse.core.runtime plug-in so if you have a dependency on that then the above should allow you to get access to your resource.