目录在ant构建后变成文件。怎么处理?

时间:2015-03-27 12:20:11

标签: java ant antbuilder

以下方法应该从某个目录中读取类/文件。在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

1 个答案:

答案 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());
}