Collapsing parent POM into the child

后端 未结 3 898
半阙折子戏
半阙折子戏 2021-02-09 21:44

Given a maven project with a parent POM - including mostly plugin and dependency versions - how can I generate a POM which takes the information from the parent, places it into

3条回答
  •  抹茶落季
    2021-02-09 22:32

    I had a similar issue a while back, you can avoid Maven substituting for the properties and resolving paths etc. by defining a new Maven plugin to do the following.

    • Resolve each parent using the standard artifact factory
    • Read each pom file (without resolving it) using the MavenXpp3Reader
    • Merge the unresolved projects
    • Write the merged project to a file

    Here is some test code I used to prove the process for myself, you'd obviously need to wrap this up in a Maven plugin and bind that to some phase of your process. The resolved pom is output to the output directory (i.e. target) with the name resolved-pom.xml by default, these two properties can be overridden with the usual Maven plugin configuration approach by setting the "outputDir" and/or "pomfileName" properties.

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

提交回复
热议问题