如何获得完全解析的pom文件模型?

如何获得完全解析的pom文件模型?

这基本上是我如何编程构建pom文件的有效模型的改述?

我正在构建一个maven插件,它针对一组模块执行一些validation规则。 这些模块的pom文件可用,但在执行插件时它们不是反应器的一部分。

我可以使用此方法读取pom文件并获取相应的Model对象(为简单起见,删除了exception处理):

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的所有其他内容。

干杯!

我做的 :-)

帮助:有效的pom和依赖:树根本没有帮助。

我不得不看看maven如何构建MavenProject的模型,它被注入mojo中。 help:effective-pom已经收到已解析的Model,依赖:tree只构建一个DependencyGraph,但它不会将pom的整个模型加载到内存中。

通过使用下面的代码,我能够获得一个Model对象,其中包含来自父级的所有信息,具有已解析的$ {property}表达式,以及扩展的传递依赖性。

就是这样:

1)获取ModelResolver

您将需要一个接口org.apache.maven.model.resolution.ModelResolver的实例。 不幸的是,maven不能通过dependency injection轻松提供一个(至少我找不到),所以我们必须构建一个。 为了使事情变得更好,该接口的唯一两个实现是包保护的,因此您需要使用一些reflection魔法来实例化它。 实现它的具体类是DefaultModelResolverProjectModelResolver 。 我能够像这样构建一个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

Romain提供了上面的好答案,但它使用的是从maven 3.x中删除的已弃用的类。更新后的版本如下:

 @Parameter( defaultValue = "${project}", readonly = true ) private MavenProject project; @Component private RepositorySystem repositorySystem; @Component private ProjectBuilder mavenProjectBuilder; @Parameter( defaultValue = "${session}", readonly = true ) private MavenSession session; private MavenProject getMavenProject(String groupId, String artifactId, String version) throws ProjectBuildingException { Artifact pomArtifact = repositorySystem.createProjectArtifact(groupId, artifactId, version); ProjectBuildingResult build = mavenProjectBuilder.build(pomArtifact, session.getProjectBuildingRequest()); return build.getProject(); } 

一个工作示例位于hierarchy-maven-plugin中

也许对你来说太迟了,但如果它可以在将来帮助别人。 所以我这样做了:

 @Component private RepositorySystem repositorySystem; @Component private MavenProjectBuilder mavenProjectBuilder; @Parameter(property = "project.remoteArtifactRepositories") protected List remoteRepositories; @Parameter(property = "localRepository") protected ArtifactRepository localRepository; ... Artifact pomArtifact = repositorySystem.createProjectArtifact(groupId, artifactId,version); MavenProject project = mavenProjectBuilder.buildFromRepository(pomArtifact , remoteRepositories, localRepository); 

就是这样。 它应该工作。 如果你有一些特殊的包装(例如捆绑…)在目标pom项目中,确保与当前项目中安装的那些包装相关的插件。

当执行“mvn help:effective-pom”时,maven帮助插件会执行类似的操作。

请参阅http://svn.apache.org/viewvc/maven/plugins/tags/maven-help-plugin-2.1.1/src/main/java/org/apache/maven/plugins/help/EffectivePomMojo.java?view =来源的标记 。

我认为这不会显示传递依赖性。

mvn依赖:树目标是这样的: http : //svn.apache.org/viewvc/maven/plugins/tags/maven-dependency-plugin-2.4/src/main/java/org/apache/maven/plugin/dependency /TreeMojo.java?view=markup

也许你可以创造两者的混合?

您寻求的源代码在help:effective-pom ,somewhere。

—编辑更新—

快速浏览之后,您似乎需要从读取pom构建Maven Project 。 这可能涉及许多步骤,包括解决POM的父项目,下载和解析其他Maven插件工件以及将所有引用连接在一起。

单独阅读儿童级别的pom是不行的。

万一有人想要它,这是一个在Groovy中运行的示例。 它使用Grape动态加载使用pom.xml所需的依赖项。 它加载运行时类路径和测试类路径。

 @Grapes([ @Grab(group='org.apache.maven', module='maven-core', version='3.0.5'), @Grab(group='org.apache.maven', module='maven-compat', version='3.0.5'), @Grab(group='com.jcabi', module='jcabi-aether', version='0.10.1') ]) // http://www.programcreek.com/java-api-examples/index.php?api=org.apache.maven.project.MavenProjectBuilder See # 20 import org.codehaus.plexus.DefaultPlexusContainer import org.apache.maven.project.MavenProjectBuilder import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.project.DefaultProjectBuilderConfiguration import org.apache.maven.artifact.repository.DefaultArtifactRepository import com.jcabi.aether.Aether import org.sonatype.aether.repository.RemoteRepository; import org.sonatype.aether.util.artifact.DefaultArtifact; import org.sonatype.aether.artifact.Artifact; container=new DefaultPlexusContainer(); projectBuilder=(MavenProjectBuilder)container.lookup(MavenProjectBuilder.class.getName()); layout=(ArtifactRepositoryLayout)container.lookup(ArtifactRepositoryLayout.class.getName(),"default"); def projectInfo(localRepoUrl, pom){ File pomFile = new File(pom); String localRepoUrl2 = "file://" + localRepoUrl; File local = new File(localRepoUrl); ArtifactRepository localRepo=new DefaultArtifactRepository("local",localRepoUrl2,layout); pbConfig=new DefaultProjectBuilderConfiguration().setLocalRepository(localRepo); project = projectBuilder.build( pomFile, pbConfig ); aether = new Aether(project, local); [ runtime: resolveDependencies(aether, project, "runtime"), test : resolveDependencies(aether, project, "test") ]; } def resolveDependencies (aether, project, scope) { depLists = project.getDependencies().collect { art = new DefaultArtifact(it.getGroupId(), it.getArtifactId(), it.getClassifier(), it.getType(), it.getVersion()); Collection deps = aether.resolve( art, scope ); deps.collect{ it.getFile().getAbsolutePath() } } [ dependencies : depLists.collect {it.first()}, classpath : depLists.flatten() ] } println projectInfo("c:/Users/lpmsmith/.m2/repository", "pom.xml");