有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

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

这基本上是对How can i programmaticaly build the effective model of a pom file?的重新表述

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

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

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;
}

它可以工作,但是模型对象只有pom文件所具有的相同信息

如何改进该方法以获得“完全解析”的模型对象? 通过完全解析,我的意思是:具有所有可传递的依赖项以及来自父POM的所有其他内容

干杯


共 (6) 个答案

  1. # 1 楼答案

    maven帮助插件在执行“mvn帮助:有效pom”时也会执行类似的操作

    有关来源,请参见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=markup

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

    mvn dependency:tree的目标是: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

    也许你可以把两者结合起来

  2. # 2 楼答案

    我做到了:-)

    帮助:有效的pom和依赖性:tree确实没有帮助

    我必须看看maven是如何为注入mojo的MavenProject构建模型的。 帮助:有效的pom已经收到已解析的模型,dependency:tree只构建DependencyGraph,但它不会将pom的整个模型加载到内存中

    通过使用下面的代码,我能够获得一个模型对象,其中包含来自父对象的所有信息、解析的${property}表达式和扩展的可传递依赖项

    以下是方法:

    1)获取模型解析程序

    您将需要一个接口组织的实例。阿帕奇。专家模型决议ModelResolver。 不幸的是,maven不容易通过依赖注入提供一个(至少我找不到),所以我们必须构建一个。 为了让事情变得更好,该接口仅有的两个实现是包保护的,因此您需要使用一些反射魔法来实例化它。 实现它的具体类是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

  3. # 3 楼答案

    为了以防万一,下面是一个在Groovy中运行的示例。它使用葡萄动态加载消耗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<Artifact> 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");
    
  4. # 4 楼答案

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

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

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

  5. # 5 楼答案

    Romain提供了一个很好的答案above,但它使用了一个从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

  6. # 6 楼答案

    您寻找的源代码位于help:effective-pom的某个地方

    ---编辑更新--

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

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