Reputation: 8654
I have a Maven project, and I am packaging it as a single fat jar using the One-Jar Maven plugin. According to this page on the One-Jar site documentation resource loading must be done in a special manner with One-Jar packaged apps, however that documentation does not cover how to list the resources in a manner which does not depend on their custom class loader.
My question is this: how to I list the contents of the root of my classpath within an inner jar in a packaging agnostic manner, meaning not assuming it will always be in such special packaging? As covered in this SO question, Spring's PathMatchingResourcePatternResolver
will not work because Spring's DefaultResourceLoader
ignores the classloader.
NOTE: The closest SO question I could find was this question, but this does not address the listing of classpath resources from nested jars.
Upvotes: 0
Views: 1512
Reputation: 813
It can be done in a FAT jar. Your own answer stating it's not possible has a link to a page that shows it's possible! It's not that insane of a solution. Here's a slightly modified version:
private List<String> getResourceFiles(String path) throws IOException
{
List<String> files = new ArrayList<>();
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
URL dirURL = classLoader.getResource(path);
if (dirURL.getProtocol().equals("jar"))
{
String jarPath = dirURL.getPath().substring(5, dirURL.getPath().indexOf("!"));
try (final JarFile jar = new JarFile(URLDecoder.decode(jarPath, "UTF-8")))
{
Enumeration<JarEntry> entries = jar.entries();
while (entries.hasMoreElements())
{
String name = entries.nextElement().getName();
if (name.startsWith(path + "/") && !name.endsWith("/"))
{
files.add(name);
}
}
}
return files;
}
// return some other way when not a JAR
}
This version will return the full resource path of any file under the given resource path, recursively. For example, an input of config/rest
would return files under that resource folder as:
config/rest/options.properties
config/rest/samples/data.json
With those values, one can get the resource with ClassLoader::getResource
, or get the contents of the resource with ClassLoader::getResourceAsStream
.
Upvotes: 1
Reputation: 8654
After reviewing many articles, and blogs posts, web pages, site and the Spring source code, I had concluded this is just a weakness in Java and is not possible in any sane manner.
Upvotes: 0