def loadResources(onBehalfOf: Class[_])(path: String): List[Path] = {
val url: URL = onBehalfOf.getClassLoader.getResource(path)
if (url.toURI.getScheme.contains("jar")) {
val jar: URL = onBehalfOf.getProtectionDomain.getCodeSource.getLocation
val jarFile: Path = Paths.get(jar.toString.substring("file:".length))
val fs: FileSystem = FileSystems.newFileSystem(jarFile, null)
val directoryStream: DirectoryStream[Path] = Files.newDirectoryStream(fs.getPath(path))
directoryStream.asScala.toList
} else {
val path: Path = Paths.get(url.toURI)
val directoryStream: DirectoryStream[Path] = Files.newDirectoryStream(path)
directoryStream.asScala.toList
}
}
This is the only generic way I've found to load, from within a library, resources provided by the wrapping app. E.g. library like Flyway
looks for migration scripts in the classpath of the invoker app. It needs to know the physical location of that class, in order to open a file system around it and access the files.
A trivial Java solution would be
final ClassLoader classLoader = getClass().getClassLoader();
final URL resource = classLoader.getResource(dirPath);
final String file = resource.getFile();
final File[] fileArr = new File(file).listFiles((dir, name) -> true);
The only case in which such a solution works, is when dealing with a fat jar, or an exploded, unpackaged application.