如何获得pom文件的完全解析模型?
这基本上是How can i programmaticaly build the effective model of a pom file?的改写
我正在构建一个对一组模块执行一些验证规则的Maven插件。
这些模块的pom文件可用,但是执行插件时它们不属于反应堆。
我可以使用此方法读取pom文件并获取相应的Model对象(为简单起见,删除了异常处理):
private Model pomToModel(String pathToPom) throws Exception {
BufferedReader in = new BufferedReader(new FileReader(pathToPom));
MavenXpp3Reader reader = new MavenXpp3Reader();
Model model = reader.read(in);
return model;
}
它可以工作,但是Model对象仅具有与pom文件相同的信息。
如何改进该方法,以便获得“完全解析”的Model对象?
通过完全解决,我的意思是:具有所有传递依赖项以及父poms的所有其他项。
干杯!
最佳答案
我做的 :-)
help:有效pom和dependency:tree根本没有帮助。
我必须看一下maven如何为注入到mojo中的MavenProject构建模型。
help:effective-pom已经收到了解析的模型,并且dependency:tree只建立了一个DependencyGraph,但没有将整个pom模型加载到内存中。
通过使用下面的代码,我可以从父级获得所有信息的Model对象,并具有解析的$ {property}表达式和扩展的传递依赖关系。
这是如何做:
1)获取一个ModelResolver
您将需要接口org.apache.maven.model.resolution.ModelResolver的实例。
不幸的是,maven无法通过依赖注入轻松地提供一个(至少我找不到一个),因此我们必须构建一个。
为了使事情变得更好,该接口的仅有两个实现受到包保护,因此您需要使用一些反射魔术来实例化它。
实现它的具体类是DefaultModelResolver和ProjectModelResolver。
我能够建立像这样的DefaultModelResolver
/**
* The Maven Project Object
*
* @parameter expression="${project}"
* @required2.0
* @readonly
*/
protected MavenProject project;
/**
* @component
*/
protected ArtifactResolver artifactResolver;
/**
* @component
*/
protected RemoteRepositoryManager remoteRepositoryManager;
private Object invoke( Object object, String method )
throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
return object.getClass().getMethod( method ).invoke( object );
}
private org.apache.maven.model.resolution.ModelResolver makeModelResolver() throws MojoExecutionException {
try {
ProjectBuildingRequest projectBuildingRequest =
(ProjectBuildingRequest) invoke( project, "getProjectBuildingRequest" );
Class c = Class.forName("org.apache.maven.repository.internal.DefaultModelResolver");
Constructor ct = c.getConstructor(new Class[]{RepositorySystemSession.class,
RequestTrace.class, String.class,
ArtifactResolver.class, RemoteRepositoryManager.class,
List.class});
ct.setAccessible(true);
return (org.apache.maven.model.resolution.ModelResolver) ct.newInstance(new Object[]{
projectBuildingRequest.getRepositorySession(),
null, null, artifactResolver, remoteRepositoryManager,
project.getRemoteProjectRepositories()});
} catch (Exception e) {
throw new MojoExecutionException("Error instantiating DefaultModelResolver", e);
}
}
2)建立模型
当您拥有modelResolver时,您可以像这样从pom文件构建模型:
public Model resolveEffectiveModel(File pomfile) {
try {
return modelBuilder.build(makeModelBuildRequest(pomfile)).getEffectiveModel();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private ModelBuildingRequest makeModelBuildRequest(File artifactFile) {
DefaultModelBuildingRequest mbr = new DefaultModelBuildingRequest();
mbr.setPomFile(artifactFile);
mbr.setModelResolver(modelResolver); // <-- the hard-to-get modelResolver
return mbr;
}
看起来不漂亮,但是对我有用。.:P