简体   繁体   中英

load resource from Jar file at runtime

I am trying to load a resource from a Jar file added in at runtime and not getting very far.

Here is my code (groovy):

URL url = new URL("jar:file:/out/resource.jar!/test.resource")
def urlList = [] << url
URL[] urls = urlList.toArray()
URLClassLoader classLoader = new URLClassLoader(urls, this.class.getClassLoader())
InputStream stream = url.openStream()

I get this error: java.util.zip.ZipException: error in opening zip file at java.util.zip.ZipFile.open(Native Method)

Questions:

1) do I need to put "test.resource" in my url? 2) What is the relationship between my URLClassLoader and my current class's classloader? 3) what is the proper way to stream in this resource (obviously what I have doesn't work)?

Thanks

If you want to add a JAR file to your current thread's ClassLoader you'd create a new URLClassLoader, use the current class's ClassLoader as parent and add the new JAR URLs. You may not put test.resource in your URL. Don't forget to assign the new ClassLoader to your current thread. See the example below:

URL url = new URL("file:/out/resource.jar")
def urlList = [] << url
URL[] urls = urlList.toArray()
URLClassLoader classLoader = new URLClassLoader(urls, getClass().classLoader)
Thread.currentThread().setContextClassLoader(classLoader)

Now you should be able to get the file via Thread.currentThread().getContextClassLoader().getResourceAsStream .

If you actually just want to read the file from a JAR without adding it to your classpath you can take the following approach:

JarFile jar = new JarFile(new File('/out/resource.jar'))
JarEntry jarEntry = jar.getJarEntry('test.resource')

if(jarEntry) {
    File file = new File(new URL("jar:file:/out/resource.jar!/test.resource").toURI())
}

I'm more familiar with java than groovy, but this should give you the InputStream you asked for:

JarFile jarFile = new JarFile(new File("/out/resource.jar"))
JarEntry jarEntry = jarFile.getJarEntry("test.resource")
InputStream inputStream = jarFile.getInputStream(jarEntry)

No need to worry about ClassLoader unless:

  1. You are trying to load classes (eg as plugins),
  2. Your resources are located within some package structure, or
  3. You are loading resources within an OSGi environment with multiple distinct ClassPaths and ClassLoaders (in which case you might use something like org.eclipse.core.runtime.FileLocator#resolve(URL) )

If the jar file is in your classpath already then you should just be able to do Classloader.getResourceAsStream

Is this jar outside your current classpath?

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