以下方法应该从某个目录中读取类/文件。在eclipse中调试方法时,它可以正常工作。但是在使用ant构建它之后,扫描的目录不再是目录了。有谁知道如何更改它,以便它在部署后仍然有效?提前谢谢!
private static List<Class<?>> find(String scannedPackage) {
logger.trace("Scanned package='{}'", scannedPackage);
String scannedPath = scannedPackage.replace(DOT, SLASH);
logger.trace("Scanned path='{}'", scannedPath);
URL scannedUrl = Thread.currentThread().getContextClassLoader().getResource(scannedPath);
logger.trace("Scanned url='{}'", scannedUrl);
if (scannedUrl == null) {
throw new IllegalArgumentException(String.format(BAD_PACKAGE_ERROR, scannedPath, scannedPackage));
}
File scannedDir = new File(scannedUrl.getFile());
logger.trace("scannedDir.isDirecory='{}'", scannedDir.isDirectory());
List<Class<?>> classes = new ArrayList<Class<?>>();
for (File file : scannedDir.listFiles()) {
logger.trace("currentFile='{}'", file.getAbsolutePath());
classes.addAll(find(file, scannedPackage));
}
return classes;
}
所以详细说明:当我使用eclipse调试模式scannedDir.isDirectory=true
运行它时。但在构建它之后scannedDir.isDirectory=false
干杯!
编辑:
scannedDir.getAbsolutePath()
返回jar:file:/C:/Users/xxx.xxx/AppData/Local/XBRLGEN/app/xbrl_s2.jar!/eu/europa/eiopa/xbrl/s2c/dict/dom
答案 0 :(得分:0)
您无法处理像File
这样的jar文件中的条目,这些条目永远不会有效。你也误解了这个问题。仅仅因为File
表示它不是一个目录并不意味着它是一个普通的文件,它就不存在,因为你已经提取了一部分jar:
URL并被解释为一个普通的文件。
以下是处理不需要普通文件的抽象的任务的解决方案:
private static Set<Class<?>> getClasses(String pkg)
throws IOException, URISyntaxException {
ClassLoader cll = Thread.currentThread().getContextClassLoader();
URI clURI = cll.getResource(pkg.replace('.', '/')).toURI();
if(!clURI.getScheme().equals("file")) try {
FileSystems.getFileSystem(clURI);
} catch(FileSystemNotFoundException ex) {
FileSystems.newFileSystem(clURI, Collections.emptyMap());
}
return Files.list(Paths.get(clURI))
.map(p->p.getFileName().toString())
.filter(s->s.endsWith(".class"))
.map(s->s.substring(0, s.length()-6))
.map(s-> { try {
return cll.loadClass(pkg+'.'+s);
} catch(ClassNotFoundException ex) { return null; } })
.filter(Objects::nonNull)
.collect(Collectors.toSet());
}
但它不可靠,因为jar
文件根本不需要包含目录条目。在缺少条目的情况下,仅存在目录,因为存在该目录内的常规文件的条目,例如,条目foo/bar
表示存在目录foo
。在这种情况下,目录的getResource
次尝试将失败。
查询包的最安全的方法是在该包中选择一个类并对其执行查找,因为相关的资源肯定存在。然后你可以遍历它的父元素,即使它的存在只是暗示:
private static Set<Class<?>> getClasses(Class<?> context)
throws IOException, URISyntaxException {
ClassLoader cll = context.getClassLoader();
URI clURI = context.getResource(context.getSimpleName()+".class").toURI();
if(!clURI.getScheme().equals("file")) try {
FileSystems.getFileSystem(clURI);
} catch(FileSystemNotFoundException ex) {
FileSystems.newFileSystem(clURI, Collections.emptyMap());
}
String pkg=context.getPackage().getName();
return Files.list(Paths.get(clURI).getParent())
.map(p->p.getFileName().toString())
.filter(s->s.endsWith(".class"))
.map(s->s.substring(0, s.length()-6))
.map(s-> { try {
return Class.forName(pkg+'.'+s, false, cll);
} catch(ClassNotFoundException ex) { return null; } })
.filter(Objects::nonNull)
.collect(Collectors.toSet());
}