目录在蚂蚁构建后变成文件。如何处理?

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

您不能像 Files 那样处理 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());
}