简体   繁体   中英

How to load resources from within a jar file loaded in a java application?

So, I have a main application that should load a jar that contains code and other resources (ie: jar files, text files, java properties etc.). I use:

JarFile jar  = new JarFile(jar);
Enumeration<JarEntry> entries = jar.entries();

int URLsize = 1;
while (entries.hasMoreElements())
    if (entries.nextElement().getName().startsWith("foo/bar/foobar"))
        URLsize++;

entries = jar.entries();

URL[] urls = new URL[URLsize];
urls[0] = patch.toURI().toURL();

int count = 1;
while (entries.hasMoreElements())
{
    JarEntry nextElement = entries.nextElement();
    if (nextElement.getName().startsWith("foo/bar/foobar"))
    {               
        urls[count] = new URL("jar:file:/"+ jar.getAbsolutePath() + "!/" + nextElement.getName());

        count++;
    }
}

to load the resources of the jar, and an URLClassLoader plus some reflection to get all resources together and execute the jar's main class, like this:

URLClassLoader loader = new URLClassLoader (urls);
Thread.currentThread().setContextClassLoader(loader);

Class<?> jarC = Class.forName ("foo.bar.barfoo.Main", true, loader);
Constructor<?> cons = jarC.getConstructor(String.class, String.class, Properties.class, Properties.class, String[].class);
Object instance = cons.newInstance (systemPath, programPath, config, some_data, args);

Method method = jarC.getMethod ("Main");

method.invoke (instance);

Now the problem is that inside the loaded jar's code when I try to load a bunch of files (resources) from a package inside the jar (eg: /foo/bar/foobar) it throws a NullPointerException .

private static InputStream getResourceAsStream(String resource) {       
        try {       
            return Thread.currentThread().getContextClassLoader().getResource(resource).openStream();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

That's how I try to get the package that than gets parsed with a BufferedReader and an InputStreamReader to get the names of each resource inside the package. Okay, maybe a bit too detailed (this is just one way I use the getResourceAsStream method), but I hope I made myself understood, the ContextClassLoader doesn't contain the resources I loaded in the application that runs this jar within itself, so what do I need to do to get those from within the loaded jar?

EDIT: Calling the getResourceAsStream method:

private static List<String> getResourceFiles(String path) throws IOException {
    List<String> filenames = new ArrayList<>();

    try (
            InputStream in = getResourceAsStream(path);
            BufferedReader br = new BufferedReader(new InputStreamReader(in))) {
        String resource;

        while ((resource = br.readLine()) != null) {
            filenames.add(resource);
        }
    }

    return filenames;
}

And where the getResourceFiles method is called:

List<String> names = Foo.getResourceFiles("/foo/bar/foobar");

Why do you even do all this? Why not just add URL to JAR to the URLClassLoader?

Eg

URLClassLoader loader = new URLClassLoader(new File(jar).toURI().toURL());

Also you should probably make that URLClassLoader have your current classloader as parent, eg

URLClassLoader loader = new URLClassLoader(new File(jar).toURI().toURL(), Thread.currentThread().getContextClassLoader());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM