4

Java Compiler API 是否支持仅清单 jar 文件,其中Class-Path包含类路径参数中的条目?

我正在尝试在 Maven Surefire 测试中使用 Java Compiler API,但似乎 Java Compiler API,或更准确地说ToolProvider.getSystemJavaCompiler(),不能正确处理仅清单的 Surefire jar。

这是一个显示失败测试的代码片段

    new File("target/out").mkdir();
    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    URLClassLoader classLoader = (URLClassLoader)Thread.currentThread().getContextClassLoader();

    // create classpath
    StringBuilder path = new StringBuilder();
    for (URL url : ((URLClassLoader) classLoader).getURLs()) {
        if (path.length() > 0) {
            path.append(File.pathSeparator);
        }
        String decodedPath = URLDecoder.decode(url.getPath(), "UTF-8");
        path.append(new File(decodedPath).getAbsolutePath());
    }
    System.err.println(path);

    // compile
    List<String> options = Arrays.asList(
      "-classpath", path.toString(),      
      "-s", "target/out",
      "src/test/java/com/mysema/codegen/SimpleCompilerTest.java");
    int compilationResult = compiler.run(null, null, null,
            options.toArray(new String[options.size()]));
    if (compilationResult != 0) {
        Assert.fail("Compilation Failed");
    }
4

1 回答 1

2

我在surefire单元测试中运行带有jsp编译的嵌入式码头时遇到了类似的问题。更简单的解决方案是将surefire插件配置为不使用仅清单jar

  <plugin>
    <artifactId>maven-surefire-plugin</artifactId>
    <configuration>
      <useManifestOnlyJar>false</useManifestOnlyJar>
    </configuration>
  </plugin>

更难的解决方案是扩展类路径以包含从清单类路径字段引用的 jar 文件

static List<String> getClassPathForJspCompiler() throws IOException {
    List<String> classPath = Lists.newArrayList(System.getProperty("java.class.path")
            .split(File.pathSeparator));
    return expandManifestClassPathElements(classPath);
}

private static List<String> expandManifestClassPathElements(List<String> classPath)
        throws IOException {
    for (int i = 0; i < classPath.size(); i++) {
        String element = classPath.get(i);
        if (element.endsWith(".jar")) {
            for (String manifestElement : getManifestClassPath(element)) {
                // add to the end of the class path so it will get processed
                if (!classPath.contains(manifestElement)) {
                    // only add if not already present to prevent cyclic loop
                    classPath.add(manifestElement);
                }
            }

        }
    }
    return classPath;
}

private static List<String> getManifestClassPath(String jarFilePath) throws IOException {
    File jarFile = new File(jarFilePath);
    if (!jarFile.isFile()) {
        return ImmutableList.of();
    }
    Manifest manifest = new JarFile(jarFile).getManifest();
    if (manifest == null) {
        return ImmutableList.of();
    }
    String manifestClassPath = manifest.getMainAttributes().getValue(
            Attributes.Name.CLASS_PATH);
    if (manifestClassPath == null) {
        return ImmutableList.of();
    }
    // split at all spaces that are not preceded by a backslash
    return Lists.newArrayList(manifestClassPath.split("(?<!\\\\) "));
}
于 2012-10-11T09:14:47.717 回答