1

I am using reflection to find all the directories in a certain package, and then returning those directories as java.io.Files so that I can extract class files from them. My method for getting all the directories in a package is this:

private static List<File> findDirs(String packageName) throws IOException,
        UnsupportedEncodingException, URISyntaxException {
    List<File> result = new ArrayList<File>();
    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    assert classLoader != null;

    String path = packageName.replace('.', '/');
    Enumeration<URL> resources = classLoader.getResources(path);
    while (resources.hasMoreElements()) {
        URL resource = resources.nextElement();
        URI uri = resource.toURI();
        File f = new File(uri);// this line throws the exception
        result.add(f);
    }
    return result;
}

It works perfectly fine when running my application from the source code. However, Once I deploy it,and run it, the method findDirs fails, as the File constructor throws an IllegalArgumentsException"URI is not Hierarchical".

I have debuged the code, and the URI in question which is causing the problem is: jar:file:/C:/Program%20Files/apache-activemq-5.5.1/bin/../lib/App.jar!/com/demo/payload

Whereas I have no problem with the URI when running from source: file:/C:/Marcus/JavaProjects/App/build/prod/classes/com/demo/payload

How can I create a file pointing to the payload directory within the App.jar from a non-herarchical URI such as the one mentioned?

I can get as far as creating a JarFile that points to the App.jar itself using JarURLConnection, and can then get a JarEntry pointing to the directory I'm searching for, but can't seem to convert this entry to a file...

2 Answers 2

1

It is wrong to expect you'll be able to treat all stuff you get from #getResources(String) are valid File references. In your run case, it's a reference of a file within your application/library's Jar. You should access these URLs as such: get InputStreams (URL#openStream) on them to read the contents instead of trying to hop through File.

In order to get Files, you'll need to figure out when you're looking at an in-jar URL, then possibly extract the file from the ZIP (because JARs are ZIPs) in order to get a proper, first-class citizen File.

Sign up to request clarification or add additional context in comments.

4 Comments

-1, as it does not answer the question at all (even though the facts stated are valid)
Agreed, but unfortunately I am working with other peoples code here, and to avoid having to rewrite the entire class I need the findDirs method to return a File pointing to a directory, whether the directory is in a Jar or on the fileSystem, Is there any way to do this?
@stryba Added notes about getting stuff from Zip. However, it's not something I would recommend doing in a production setup - it's dangerous, classloaders could reference remote data.
@Romain: agreed not a recommendable solution to the problem
0

You can use java.util.zip.ZipFile whenever you point to the inside of a jar file. Just load the referenced jar file in a ZipFile and use getEntry or entries of it to retrieve elements within the jar.

2 Comments

As I said at the end of the question I am able to get access to the underlying Zipentry that corresponds to the directory I'm trying to create a file for, but then how can I actually Create a java.io.File instance from this entry?
The question is whether you need a List<File> rather then something like List<URL> or List<URI> for that matter. With File you won't solve this problem.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.