views:

123

answers:

3

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 http://stackoverflow.com/questions/1411812/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");

A: 

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.

Manuel Selva
Is there anyway to access it outside of the context of the BundleActivator? I'm guessing you are referring to do something like this: public void start(BundleContext context) { Bundle bundle = context.getBundle(); InputStream in = bundle.getEntry("/resource/example.css").openStream();}. However, I am looking for a solution (if there is any) to access it outside of the BundleActivator. I had a look at http://www.eclipsezone.com/eclipse/forums/t101557.html but am still confused
herbertyeung
Have you look on a way to get a Bundle object from the bundle id ?
Manuel Selva
I can get the entry, but the problem is that getEntry() only supplies the relative path, and not the full (root) path of the bundle: http://www.techinfopad.com/spring/101600333-getting-root-path-of-a-bundle.html.
herbertyeung
+2  A: 

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.

tbone
I am trying to avoid using the org.eclipse.core.runtime plugin as for our deployment the decision was made to use Apache Felix (unless there is a means of incorporating this). The above works if I run it under the Eclipse runtime environment.
herbertyeung
+1  A: 

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");
Neil Bartlett
I have opted for this solution but had issues with trying to import all the directory's values e.g. I am using BluePrint CSS and had issues with this.getClass().getClassLoader().getResource("resources/css") because there are not only many files but sub directories as well. I ended up 'copying' the files to a temporary location, but this induces some performance issues.
herbertyeung