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 the child and removes the reference to the parent?
给定一个带有父POM的maven项目 - 主要包括插件和依赖版本 - 如何生成一个从父项获取信息的POM,将其放入子项并删除对父项的引用?
Ideally this would be done with the maven-assembly-plugin.
理想情况下,这将使用maven-assembly-plugin完成。
Update: I need this done automatically, since manually it's boring and tedious.
更新:我需要自动完成此操作,因为手动操作很乏味且乏味。
Update 2: I'm preparing the source code for an external and want to deliver only one project, not the whole family.
更新2:我正在准备外部的源代码,并且只想提供一个项目,而不是整个系列。
3 个解决方案
#1
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.
我有一个类似的问题,你可以避免Maven替换属性和解析路径等,通过定义一个新的Maven插件来执行以下操作。
- 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
使用标准工件工厂解析每个父级
使用MavenXpp3Reader读取每个pom文件(不解析它)
合并未解决的项目
将合并的项目写入文件
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.
下面是我用来为自己证明这个过程的一些测试代码,你显然需要将它包装在一个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
Would mvn help:effective-pom
do what you need? You can send the output to a file with -Doutput=new-pom.xml
.
mvn会帮助:有效的pom做你需要的吗?您可以使用-Doutput = new-pom.xml将输出发送到文件。
#3
If you don't want a parent you can try the BOM (Bill of materials) pattern and select that pom for import in your dependancy management section.
如果您不想要父母,您可以尝试BOM(物料清单)模式,并在您的依赖管理部分选择要导入的pom。
Since you want no references to anything else, you will need to build an app to parse the xml from the "parents" and then write them to the target pom file in the dependencies section. I don't think there is any plugin to do what you want since it seems to go against the very core of how maven is supposed to help you. The whole point of maven is so that you can include all your dependancies using inheritance or importing them with the import scope.
由于您不想引用任何其他内容,因此您需要构建一个应用程序来解析“父”中的xml,然后将它们写入依赖项部分中的目标pom文件。我不认为有任何插件可以做你想要的,因为它似乎违背了maven应该如何帮助你的核心。 maven的全部意义在于您可以使用继承包含所有依赖项或使用导入范围导入它们。
Another option, but I think you've excluded it, is to maintain your releasable POM file separately. Though I think you may find an easier time with this if you reference LATEST or SNAPSHOTS and then use the release plugin to resolve them to released versions.
另一个选项,但我认为你已经排除它,是分开维护你的可释放的POM文件。虽然我认为如果您引用LATEST或SNAPSHOTS然后使用发布插件将它们解析为已发布的版本,您可能会更容易找到它。
#1
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.
我有一个类似的问题,你可以避免Maven替换属性和解析路径等,通过定义一个新的Maven插件来执行以下操作。
- 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
使用标准工件工厂解析每个父级
使用MavenXpp3Reader读取每个pom文件(不解析它)
合并未解决的项目
将合并的项目写入文件
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.
下面是我用来为自己证明这个过程的一些测试代码,你显然需要将它包装在一个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
Would mvn help:effective-pom
do what you need? You can send the output to a file with -Doutput=new-pom.xml
.
mvn会帮助:有效的pom做你需要的吗?您可以使用-Doutput = new-pom.xml将输出发送到文件。
#3
If you don't want a parent you can try the BOM (Bill of materials) pattern and select that pom for import in your dependancy management section.
如果您不想要父母,您可以尝试BOM(物料清单)模式,并在您的依赖管理部分选择要导入的pom。
Since you want no references to anything else, you will need to build an app to parse the xml from the "parents" and then write them to the target pom file in the dependencies section. I don't think there is any plugin to do what you want since it seems to go against the very core of how maven is supposed to help you. The whole point of maven is so that you can include all your dependancies using inheritance or importing them with the import scope.
由于您不想引用任何其他内容,因此您需要构建一个应用程序来解析“父”中的xml,然后将它们写入依赖项部分中的目标pom文件。我不认为有任何插件可以做你想要的,因为它似乎违背了maven应该如何帮助你的核心。 maven的全部意义在于您可以使用继承包含所有依赖项或使用导入范围导入它们。
Another option, but I think you've excluded it, is to maintain your releasable POM file separately. Though I think you may find an easier time with this if you reference LATEST or SNAPSHOTS and then use the release plugin to resolve them to released versions.
另一个选项,但我认为你已经排除它,是分开维护你的可释放的POM文件。虽然我认为如果您引用LATEST或SNAPSHOTS然后使用发布插件将它们解析为已发布的版本,您可能会更容易找到它。