目录在蚂蚁构建后变成文件。如何处理?
Directory turns into file after ant build. How to handle that?
下面的方法应该从某个目录中读取 classes/files。在eclipse中调试该方法时它工作正常。但是在使用 ant 构建它之后,scannedDir 不再是一个目录。有谁知道如何更改它以便它在部署后仍然有效?提前致谢!
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()
returns jar:file:/C:/Users/xxx.xxx/AppData/Local/XBRLGEN/app/xbrl_s2.jar!/eu/europa/eiopa/xbrl/s2c/dict/dom
您不能像 File
s 那样处理 jar 文件中的条目,那将永远行不通。你也误解了这个问题。仅仅因为 File
说它不是目录并不意味着它是一个普通文件,它根本不存在,因为您提取了 jar:
[=28= 的一部分] 并解释为普通文件。
这是你的任务的解决方案,不需要普通文件:
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
次尝试将失败。
查询包最安全的方法是在该包中选择一个 class 并对其执行查找,因为相关资源确实存在。然后你可以遍历它的父级,即使它的存在只是隐含的:
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());
}
下面的方法应该从某个目录中读取 classes/files。在eclipse中调试该方法时它工作正常。但是在使用 ant 构建它之后,scannedDir 不再是一个目录。有谁知道如何更改它以便它在部署后仍然有效?提前致谢!
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()
returns jar:file:/C:/Users/xxx.xxx/AppData/Local/XBRLGEN/app/xbrl_s2.jar!/eu/europa/eiopa/xbrl/s2c/dict/dom
您不能像 File
s 那样处理 jar 文件中的条目,那将永远行不通。你也误解了这个问题。仅仅因为 File
说它不是目录并不意味着它是一个普通文件,它根本不存在,因为您提取了 jar:
[=28= 的一部分] 并解释为普通文件。
这是你的任务的解决方案,不需要普通文件:
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
次尝试将失败。
查询包最安全的方法是在该包中选择一个 class 并对其执行查找,因为相关资源确实存在。然后你可以遍历它的父级,即使它的存在只是隐含的:
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());
}