Java Compiler API是否支持classpath参数中带有Class-Path条目的仅清单jar文件?
我正在尝试在Maven Surefire测试中使用Java Compiler API,但似乎Java Compiler API,或者更准确地说是ToolProvider.getSystemJavaCompiler()
,不能正确处理Surefire的仅清单罐.
这是一个显示失败测试的代码段
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");
}
解决方法:
我遇到了类似的问题,在surefire单元测试中使用jsp编译运行嵌入式jetty.更简单的解决方案是将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("(?<!\\\\) "));
}