9

I've been breaking my head over this for quite a while now and cant find a solution for this problem:

I have an Eclipse RCP application that uses a custom library packaged as jar. From the plugin, i am calling a method within the jar. Within this method, i am "getting" a resource using this.class.getResource(relPath), whereas relPath is a hardcoded relative path to a file i need. This returns me an URL which i can use to construct a File.

Now, this works perfectly if i am not calling this method from the plugin, but from a simple Java-Program. The difference: Eclipse RCP's classloader returns an URL of protocol bundleresource:// which is not supported by File, whereas when running a simple Java-program, a file://-URL is returned which is completely fine to construct a File.

I am aware of the FileLocator-class of the Eclipse SDK (which resolves bundleresource-URLs to file-URLs), but i cannot use it within the library because i dont want to tie it to the Eclipse RCP platform - it should be possible to use this lib from non-Eclipse-RCP sources as well.

Anyone any idea on how i can load this resource from a relative path in a manner that will work both when the method is called from an Eclipse RCP-Plugin or any other client?

I need to construct a File on the directory of this relative path to search for files within. I am completely stuck on this...

UPDATE: If there is a possibility other than using File#list() to get directory contents this would already help me..

any hints greatly appreciated,

quaylar
  • 2,617
  • 1
  • 17
  • 31
  • Can you list the relevant code? – Tonny Madsen Jan 28 '12 at 11:35
  • @TonnyMadsen Hm, i could but basically its very simple: I am using this.getClass().getResource(relPath) to load a path within my classPath. This returns me a bundleresource:// URL when done under Eclipse RCP and a file:// URL otherwise. Trying to create a File-Object fails with the bundleresource:// URL because File does not support this protocol. Since i need to read the directory contents of "relPath" i am forced to use a File... – quaylar Jan 30 '12 at 07:34
  • How do you convert the URL to a File? – Tonny Madsen Jan 30 '12 at 07:42
  • @TonnyMadsen new File(url.toURI()) – quaylar Jan 30 '12 at 07:47
  • In this case, it only works for file:// URLs... There are plugable API to convert an URL to a Stream, ut not to a File. Also noted here: http://stackoverflow.com/questions/2843557/uri-scheme-is-not-file – Tonny Madsen Jan 30 '12 at 10:17
  • @TonnyMadsen Yes i know, this is exactly my problem :) Thats why i was interested how others handle this problem, i guess there are ppl who already encountered this (loading resources using the Eclipse Classloader and in need of File-References).. – quaylar Jan 30 '12 at 12:07
  • The only solution I can come up with, is to use reflection to access `FileLocator` and convert the URIL to a `file://` based version... – Tonny Madsen Jan 30 '12 at 12:23
  • @TonnyMadsen Unfort. that's a no-go. I cant have references to Eclipse-Core classes in my library. Anyways - i appreciate your thoughts, thanks! – quaylar Jan 30 '12 at 14:20
  • You can do this by just having String references. Like `Class.forName("org.eclipse.core.runtime.FileLocator")` to get the `FileLocator` class and `class.getMethod("resolve")` to get the method... – Tonny Madsen Jan 30 '12 at 14:23
  • @TonnyMadsen: Yes but what i meant is: I then need to bundle the FileLocator-Class (and all its dependencies) with my library so that it still works when there is no Eclipse involved (i.e. it is being used in a Web-App) – quaylar Jan 30 '12 at 14:35
  • Hmm.. not sure what you mean. I would add a proper `MANIFEST.MF` file with an optional requirement for `org.eclipse.core.runtime`. – Tonny Madsen Jan 30 '12 at 21:00

2 Answers2

14

Couldn't you simply invert the dependency. I.e., your module retrieving the resource as URL defines an interface

interface Locator { URL resolve(URL url); }

and you can use a default implementation

class StandaloneLocator implements Locator {
   public URL resolve(URL url) { return url; }
}

In case of Eclipse, this default locator is to be replaced by

class EclipseLocator implements Locator {
  public URL resolve(URL url) { return FileLocator.resolve(url); }
}

Now, your library has no dependencies to Eclipse, and you can still use the FileLocator. Since you won't get any bundleresource-URLs w/o Eclipse, this should work.

Cheers, Jens

Jens
  • 299
  • 2
  • 7
  • I already circumvented the problem itself before you answered, but this is a really good idea! Appreciate it and might refactor it in next time :) – quaylar Feb 28 '12 at 08:42
0

That is not possible to enumerate files in jar file using methods from Class. You either need to create resourcelist file which will contain all your resources names, or open jar file like zip archive and enumerate files like in zip archive. File class can not handle protocols other than file://. If your rescource is in jar file, you should use Url class and get stream using Url.openSteram method to get file contents.

UPD regarding running simple java application: you probably does not pack it into jar file, so your classes and resources are placed in file system and not in archive. That is why you get file:// protocol. If you pack into jar file, protocol will not be file:// it will be jar:// (not sure about exact protocol name).

michael nesterenko
  • 14,222
  • 25
  • 114
  • 182
  • Appreciate your answer, but the file/resource is not in a jar, but in a dir within the classpath of the application. Concerning Url.openStream(): Its unfortunately not possible to read directory-contents using this method (i need to load a directory as resource and check for existing files). – quaylar Jan 30 '12 at 07:30