将父 POM 折叠到子中

Posted

技术标签:

【中文标题】将父 POM 折叠到子中【英文标题】:Collapsing parent POM into the child 【发布时间】:2010-10-31 09:36:27 【问题描述】:

给定一个带有父 POM 的 maven 项目 - 主要包括插件和依赖版本 - 我如何生成一个 POM,它从父级获取信息,将其放入子级并删除对父级的引用?

理想情况下,这将使用 maven-assembly-plugin 完成。


更新:我需要自动完成,因为手动操作很无聊且乏味。

更新 2:我正在为外部准备源代码,并且只想交付一个项目,而不是整个家庭。

【问题讨论】:

我想我遗漏了一些东西...这不能通过从父级剪切和粘贴元素来解决吗? 是的。 “生成”部分意味着自动化:-) 为什么不想引用父级。到目前为止,引用父母是阻力最小的路径。 如果您不想要父母,您可以尝试 BOM(物料清单)模式并在您的依赖管理部分中选择要导入的 pom。 您是提供源代码和 POM 文件还是只提供编译后的版本? 【参考方案1】:

不久前我遇到了类似的问题,您可以通过定义一个新的 Maven 插件来执行以下操作来避免 Maven 替换属性和解析路径等。

使用标准工件工厂解析每个父级 使用 MavenXpp3Reader 读取每个 pom 文件(无需解析) 合并未解决的项目 将合并的项目写入文件

这是我用来证明自己的过程的一些测试代码,您显然需要将其包装在 Maven 插件中并将其绑定到您的过程的某个阶段。解析后的 pom 默认输出到名称为resolved-pom.xml 的输出目录(即目标),这两个属性可以通过设置“outputDir”和/或“pomfileName”属性用通常的Maven插件配置方法覆盖.

package name.seller.rich;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.Stack;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.model.Model;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.inheritance.ModelInheritanceAssembler;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;

/**
 * @goal output-project
 * @phase process-resources
 * @requiresProject true
 */
public class OutputResolvedProjectMojo extends AbstractMojo 

    /**
     * Used to look up overlay the parent models on the project's model.
     * 
     * @parameter expression=
     *            "$component.org.apache.maven.project.inheritance.ModelInheritanceAssembler"
     * @required
     * @readonly
     */
    private ModelInheritanceAssembler modelInheritanceAssembler;

    /**
     * Used to look up Artifacts in the remote repository.
     * 
     * @parameter expression=
     *            "$component.org.apache.maven.artifact.factory.ArtifactFactory"
     * @required
     * @readonly
     */
    protected org.apache.maven.artifact.factory.ArtifactFactory factory;

    /**
     * Used to look up Artifacts in the remote repository.
     * 
     * @parameter expression=
     *            "$component.org.apache.maven.artifact.resolver.ArtifactResolver"
     * @required
     * @readonly
     */
    protected org.apache.maven.artifact.resolver.ArtifactResolver artifactResolver;

    /**
     * List of Remote Repositories used by the resolver
     * 
     * @parameter expression="$project.remoteArtifactRepositories"
     * @readonly
     * @required
     */
    protected java.util.List remoteRepos;

    /**
     * Location of the local repository.
     * 
     * @parameter expression="$localRepository"
     * @readonly
     * @required
     */
    protected org.apache.maven.artifact.repository.ArtifactRepository local;

    /**
     * @parameter expression="$project"
     * @required
     * @readonly
     */
    private MavenProject mavenProject;

    /**
     * The directory to output the resolved project to.
     * 
     * @parameter expression="$project.build.directory"
     */
    private File outputDir;

    /**
     * The directory to output the resolved project to.
     * 
     * @parameter expression="resolved-pom.xml"
     */
    private String pomfileName;

    public void execute() throws MojoExecutionException, MojoFailureException 
        MavenProject parentProject = mavenProject.getParent();

        // get the unresolved project by reading the file
        MavenProject bareProject = readBareProject(mavenProject.getFile());

        Stack hierarchy = new Stack();
        hierarchy.push(bareProject);

        try 
            while (parentProject != null) 

                try 
                    // get Maven to resolve the parent artifact (download if
                    // needed)
                    Artifact pomArtifact = this.factory.createArtifact(
                            parentProject.getGroupId(), parentProject
                                    .getArtifactId(), parentProject
                                    .getVersion(), "", "pom");

                    artifactResolver.resolve(pomArtifact, this.remoteRepos,
                            this.local);

                    // get the file from the local repository and read the bare
                    // project
                    File parentPomFile = pomArtifact.getFile();

                    parentProject = readBareProject(parentPomFile);

                    hierarchy.push(parentProject);

                    parentProject = parentProject.getParent();
                 catch (ArtifactResolutionException e) 
                    getLog().error("can't resolve parent pom", e);
                 catch (ArtifactNotFoundException e) 
                    getLog().error("can't resolve parent pom", e);
                
            

            // merge each model starting with the oldest ancestors
            MavenProject currentParent = (MavenProject) hierarchy.pop();
            MavenProject currentProject = null;
            while (hierarchy.size() != 0) 
                currentProject = (MavenProject) hierarchy.pop();
                modelInheritanceAssembler.assembleModelInheritance(
                        currentProject.getModel(), currentParent.getModel());
                currentParent = currentProject;
            

            // spit the merged model to the output file.
            Writer writer = getWriter(outputDir, pomfileName);

            if (writer != null) 
                currentProject.writeModel(writer);
                writer.close();
            
         catch (IOException e) 
            getLog().error("can't write resolved pom", e);
        

    

    /**
     * Creates and returns a writer for outputting the project to a pom file.
     * 
     * @param logDir
     *            the directory to output the file to.
     * @param logFileName
     *            name of the log file
     * @return the writer.
     * @throws IOException
     *             if the writer cannot be created.
     */
    private Writer getWriter(final File logDir, final String logFileName)
            throws IOException 
        if (!logDir.exists()) 
            logDir.mkdirs();
        

        File pomLog = new File(logDir, logFileName);

        if (!pomLog.exists()) 
            pomLog.createNewFile();
        

        return new FileWriter(pomLog);
    

    /**
     * Read the mavenProject without resolving any inherited settings.
     * 
     * @return the MavenProject for the project's POM
     * @throws MojoExecutionException
     *             if the POM can't be parsed.
     */
    MavenProject readBareProject(final File file) 
        MavenXpp3Reader reader = new MavenXpp3Reader();
        Model model = null;
        try 
            model = reader.read(new FileReader(file));
         catch (IOException e) 
            getLog().error("can't read pom file", e);
         catch (XmlPullParserException e) 
            getLog().error("can't read pom file", e);
        

        return new MavenProject(model);
    

【讨论】:

这很好,谢谢!我会尽快尝试一下。【参考方案2】:

mvn help:effective-pom 会做你需要的吗?您可以使用-Doutput=new-pom.xml 将输出发送到文件。

【讨论】:

这很有帮助,谢谢。不幸的是,所有路径都转换为绝对路径。【参考方案3】:

如果您不想要父母,您可以尝试 BOM(材料清单)模式并在您的依赖管理部分中选择要导入的 pom。

由于您不希望引用其他任何内容,因此您需要构建一个应用程序来解析来自“父母”的 xml,然后将它们写入依赖项部分的目标 pom 文件。我不认为有任何插件可以做你想做的事,因为它似乎违背了 maven 应该如何帮助你的核心。 maven 的全部意义在于,您可以使用继承或使用导入范围导入所有依赖项。

另一种选择,但我认为您已将其排除在外,是单独维护可发布的 POM 文件。虽然我认为如果您参考 LATEST 或 SNAPSHOTS 然后使用发布插件将它们解析为已发布版本,您可能会发现更轻松。

【讨论】:

更新描述:我正在为外部准备源代码,并且只想交付一个项目,而不是整个家庭。我需要它不依赖于其他工件。

以上是关于将父 POM 折叠到子中的主要内容,如果未能解决你的问题,请参考以下文章

IDEA插件系列(75):Laconic POM插件——折叠pom文件中的依赖项

为啥不能将父ajax调用的参数访问到子ajax调用中

将父分支合并到子分支

如何将父小部件焦点重定向到子小部件?

XSLT Grouping's:将父级添加到子元素中的元素集

如何使用 xslt 将父节点命名空间复制到子元素?