11

at the moment i'm developing an OSGi based WebApp with Jetty and Equinox (see: http://wiki.eclipse.org/Jetty/Tutorial/EclipseRT-Jetty-Starter-Kit). Everything ist fine so far but i can't get access to some files/resources of my own bundle. The location/path is "configuration/data/config.csv" and "configuration/data/data.zip". I have tested everything:

context.getBundleContext().getBundle().getEntry("config.csv");
context.getBundleContext().getBundle().getResource("config.csv");
this.getClass().getClassLoader().getResource("config.csv");
context.getBundleContext().getDataFile("config.csv");

And of course all possible path variants like: "configuration/data/config.csv", "/configuration/data/config.csv", "\configuration/data/config.csv", "/config.csv". Moreover i have added the folders to the OSGi classpath (in MANIFEST.MF):

Bundle-ClassPath: .,
 configuration/data/

The resulting URL looks always somthing like this (or null): "configuration/CBR-Data/config.csv" and when i transfer it to an File object "D:\configuration\CBR-Data\config.csv".

But what i really don't understand is that the properties file for one of my DS is loaded perfectly:
<properties entry="configuration/dsconfig.properties"/>

Has someone an idea/tip or something else? I'm driving crazy...

Zitzit
  • 161
  • 1
  • 1
  • 8
  • Can you post the code, which gets the URL to the resource and how you are using it afterwards. When you use getEntry() you should pass "configuration/data/config.csv" as parameter to getEntry(). The resulting URL will have the format: bundleentry://20.fwk1235/resource.txt. It seems impossible that it will have the format you've posted. So, there is something going one, which is not clear from your question. – Danail Nachev Jun 06 '11 at 10:03
  • You are right i'm sorry. The output of `URL configURL = context.getBundleContext().getBundle().getEntry("configuration/data/confid.csv");` is "bundleentry://6.fwk33311724/configuration/data/config.csv". I try transform the URL to a File via: `File configFile = new File(configURL.getPath());`. The path-output `configFile.getAbsolutePath();` is than: "D:\configuration\data\config.csv" – Zitzit Jun 06 '11 at 10:50

2 Answers2

14

You are correctly retrieving the resource from the bundle. I'll suggest to get familiar with the difference between getEntry(), getResource() and getDataFile().

Because methods returns you correct URLs, this means that the resource are correctly located and the problem is in how you read them.

The two ways to use them are:

  1. Open InputStream from the URL directly:

    URL configURL = context.getBundleContext().getBundle().getEntry("configuration/data/config.csv");
    if (configURL != null) {
        InputStream input = configUrl.openStream();
        try {
            // process your input here or in separate method
        } finally {
            input.close();
        }
    }
   
  1. Convert the URL to File. This approach is not recommended, because it makes the assumption that the Bundle is deployed as directory (and not in archive). It is however helpful if you must deal with legacy libraries which requires you to use File objects. To convert to File you cannot use URL.getPath() method, because Equinox has its own format for the URLs. You should use org.eclipse.core.runtime.FileLocator class to resolve to a File. The FileLocator.getBundleFile(Bundle) does exactly what you want.
Danail Nachev
  • 19,231
  • 3
  • 21
  • 17
  • Ok, thanks! Some questions about this: "I'll suggest to get familiar with the difference between getEntry(), getResource() and getDataFile()" Do you have some links/guides/tutorials where these differences are discribed? Moreover is there a possibility to automatically push some directorys (e.g. "configuration/data/") into the the osgi-configuration directory like it's done for the "org.eclipse.osgi" ("configuration/org.eclipse.osgi/bundles/XX")? --> something like "configuration/org.mybundle/data/config.csv". – Zitzit Jun 06 '11 at 11:52
  • @Zitzit - I don't know about any such guides, I'm relying mostly on the OSGi API javadoc (http://www.osgi.org/javadoc/r4v43/), where it is thorougly explained what each method does. Why would you want to push some directories under osgi-configuration directory (which I assume is the Equinox configuration/ folder)? This folder is specific to the Equinox, so its usage should be limited, otherwise you become dependent on Equinox. – Danail Nachev Jun 06 '11 at 13:15
4

Solved!!! Thanks to Danail Nachev (see comment) who brought me to the right way! After some searching after "bundleentry://xyz" and "bundleresource://" i found this mailinglist post: http://www.mail-archive.com/felix-dev@incubator.apache.org/msg02410.html

So the answer is the following (Usging (Equinox) FileLocator):

URL configURL = context.getBundleContext().getBundle().getResource("config.csv");
File configFile = new File(FileLocator.toFileURL(configURL).getPath());

But (also asked in that mailinglist) it would be interesting if there exists other solutionss wich are not only applicable for Equinox?

Zitzit
  • 161
  • 1
  • 1
  • 8
  • It would be better if you voted up Danail Nachev's answer. Also, rather than adding another answer to your question that says what the solution is, it would be better if you edited your original question and added the solution underneath the question. – jfenwick Jun 07 '11 at 03:31
  • http://stackoverflow.com/questions/4538898/map-with-string-is-brokensolved Here's a good example of how to change your question so it's easier to find the solution. – jfenwick Jun 07 '11 at 03:32
  • @jfenwick - I'm wondering why you think that. http://blog.stackoverflow.com/2011/07/its-ok-to-ask-and-answer-your-own-questions/ explicitly says that answering your question yourself is the right thing to do. – James Moore Jan 14 '12 at 23:05