如何允许 gradle 插件访问项目依赖项中的 类
How to allow a gradle plugin to access classes in project dependencies
我正在编写一个 gradle 插件来为我的项目中的 beans 生成一个 json-schema
。我的目标是在构建过程中生成和发布模式,这样我就不需要手动更新它了。
目前,我将 project.compileJava.inputs.files
传递给我的任务并使用它来构建 URLClassLoader
。然后我将那些 classes 传递给 schema generator.
为了确保 json 架构正确生成,我想使用来自目标应用程序的 ObjectMapper
。不幸的是,我的 ObjectMapper
添加了 jackson Hibernate5Module.
在那个模块的深处,它试图检查我的 class 是否可以分配给 HibernateProxy,
并且因为 HibernateProxy
加载了 Gradle 的 class 加载程序,我的 class 加载了 URLClassLoader
everything explodes.
我可以删除 Hibernate 模块,但这仍然会在其他类似情况下触发该错误,并且它会降低我的插件的可分发性。所以我需要一种方法来将新条目添加到 gradle 的 class 路径或在 运行 时添加到默认的 class 加载程序。
作为参考,以下是相关代码片段:
目标项目build.gradle
jsonSchema {
classpath = project.compileJava.inputs.files
}
public class WriteJsonSchema 扩展了 DefaultTask
@TaskAction
public void write() throws ClassNotFoundException, IOException {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new Hibernate5Module());
mapper.registerModule(new Jdk8Module());
mapper.registerModule(new JavaTimeModule());
mapper.configure(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS, false);
mapper.configure(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS, false);
Set<File> files = getClasspath().getFiles();
List<URL> urls = new ArrayList<URL>(files.size());
for(File file : files)
{
urls.add(file.toURI().toURL());
}
URLClassLoader classLoader = new URLClassLoader(urls.toArray(new URL[0]), Thread.currentThread().getContextClassLoader());
JsonSchemaGenerator jsonSchemaGenerator = new JsonSchemaGenerator(mapper);
JsonNode jsonSchema =
jsonSchemaGenerator.generateJsonSchema(classLoader.loadClass("com.example.Widget"));
System.out.println(mapper.writeValueAsString(jsonSchema));
classLoader.close();
}
TL;DR: 我需要一种方法来将新条目添加到 gradle 的 class 路径或默认 class 加载器在 运行 时间。
如果有人关心的话,我最终通过检查 compilejava
任务的输出获得了项目类路径。
classpath = getProject().files();
getProject()
.getTasksByName("compileJava", true)
.forEach(task -> classpath = Classpath.plus(((JavaCompile)task).getClasspath()));
classpath = Classpath.plus(getProject().getTasks().getByName("jar").getOutputs().getFiles());
我正在编写一个 gradle 插件来为我的项目中的 beans 生成一个 json-schema
。我的目标是在构建过程中生成和发布模式,这样我就不需要手动更新它了。
目前,我将 project.compileJava.inputs.files
传递给我的任务并使用它来构建 URLClassLoader
。然后我将那些 classes 传递给 schema generator.
为了确保 json 架构正确生成,我想使用来自目标应用程序的 ObjectMapper
。不幸的是,我的 ObjectMapper
添加了 jackson Hibernate5Module.
在那个模块的深处,它试图检查我的 class 是否可以分配给 HibernateProxy,
并且因为 HibernateProxy
加载了 Gradle 的 class 加载程序,我的 class 加载了 URLClassLoader
everything explodes.
我可以删除 Hibernate 模块,但这仍然会在其他类似情况下触发该错误,并且它会降低我的插件的可分发性。所以我需要一种方法来将新条目添加到 gradle 的 class 路径或在 运行 时添加到默认的 class 加载程序。
作为参考,以下是相关代码片段:
目标项目build.gradle
jsonSchema {
classpath = project.compileJava.inputs.files
}
public class WriteJsonSchema 扩展了 DefaultTask
@TaskAction
public void write() throws ClassNotFoundException, IOException {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new Hibernate5Module());
mapper.registerModule(new Jdk8Module());
mapper.registerModule(new JavaTimeModule());
mapper.configure(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS, false);
mapper.configure(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS, false);
Set<File> files = getClasspath().getFiles();
List<URL> urls = new ArrayList<URL>(files.size());
for(File file : files)
{
urls.add(file.toURI().toURL());
}
URLClassLoader classLoader = new URLClassLoader(urls.toArray(new URL[0]), Thread.currentThread().getContextClassLoader());
JsonSchemaGenerator jsonSchemaGenerator = new JsonSchemaGenerator(mapper);
JsonNode jsonSchema =
jsonSchemaGenerator.generateJsonSchema(classLoader.loadClass("com.example.Widget"));
System.out.println(mapper.writeValueAsString(jsonSchema));
classLoader.close();
}
TL;DR: 我需要一种方法来将新条目添加到 gradle 的 class 路径或默认 class 加载器在 运行 时间。
如果有人关心的话,我最终通过检查 compilejava
任务的输出获得了项目类路径。
classpath = getProject().files();
getProject()
.getTasksByName("compileJava", true)
.forEach(task -> classpath = Classpath.plus(((JavaCompile)task).getClasspath()));
classpath = Classpath.plus(getProject().getTasks().getByName("jar").getOutputs().getFiles());