kan*_*ane 3 maven-plugin maven maven-assembly-plugin
我正在编写一个Maven插件来获取已解析的依赖项.它适用于单个模块项目/ pom,但在多个模块项目上失败.
这是一段代码片段
@Mojo(
name="scan",
aggregator = true,
defaultPhase = LifecyclePhase.COMPILE,
threadSafe = true,
requiresDependencyCollection = ResolutionScope.TEST,
requiresDependencyResolution = ResolutionScope.TEST,
requiresOnline = true
)
public class MyMojo extends AbstractMojo {
@Parameter(property = "project", required = true, readonly = true)
private MavenProject project;
@Parameter(property = "reactorProjects", required = true, readonly = true)
private List<MavenProject> reactorProjects;
@Override
public void execute() throws MojoExecutionException {
for(MavenProject p : reactorProjects) {
for(Artifact a : p.getArtifacts()) {
...consolidate artifacts
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
上面的代码将整合所有模块中所有已解析的依赖项,但它包含一些额外的依赖项.
这是一个可以使用的示例项目.请下载此github repo
从modules-project主文件夹,请运行
mvn dependency:tree -Dverbose -Dincludes=commons-logging
Run Code Online (Sandbox Code Playgroud)
你应该看到这样的输出
[INFO] ------------------------------------------------------------------------
[INFO] Building core 0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ core ---
[INFO] com.github:core:jar:0.1-SNAPSHOT
[INFO] \- axis:axis:jar:1.4:compile
[INFO] +- commons-logging:commons-logging:jar:1.0.4:runtime
[INFO] \- commons-discovery:commons-discovery:jar:0.2:runtime
[INFO] \- (commons-logging:commons-logging:jar:1.0.3:runtime - omitted for conflict with 1.0.4)
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building web 0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ web ---
[INFO] com.github:web:war:0.1-SNAPSHOT
[INFO] +- commons-logging:commons-logging:jar:1.1.1:compile
[INFO] \- com.github:core:jar:0.1-SNAPSHOT:compile
[INFO] \- axis:axis:jar:1.4:compile
[INFO] +- (commons-logging:commons-logging:jar:1.0.4:runtime - omitted for conflict with 1.1.1)
[INFO] \- commons-discovery:commons-discovery:jar:0.2:runtime
[INFO] \- (commons-logging:commons-logging:jar:1.0.3:runtime - omitted for conflict with 1.1.1)
[INFO] ------------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)
请注意,模块/项目核心依赖于commons-logging 1.0.4和commons-logging 1.0.3,但由于冲突而省略了1.0.3并且解决了1.0.4.这意味着如果你要自己构建核心,你应该只获得commons-logging 1.0.4.
请注意,模块/项目Web也依赖于公共日志的冲突版本,但是解析为1.1.1.
现在,如果您使用"mvn package"命令构建"整个项目"(modules-project),您应该看到modules-project/web/target/myweb/WEB-INF/lib包含所有已解析的依赖项,并且它包括ONLY commons-logging 1.1.1.
这是代码的问题
在上面的代码中,reactorProjects使用3个MavenProject实例化:modules-project,core和web.
对于modules-project和web,它解析并返回commons-logging 1.1.1.但是,对于核心项目,它会解析并返回commons-logging 1.0.4.
我希望我的插件代码知道commons-logging 1.1.1是构建将产生的依赖,而不是commons-logging 1.0.4
有什么想法吗?
你几乎已经完成了你的所有问题.以下插件将在控制台中输出反应器中WAR项目的工件:
@Mojo(name = "foo", aggregator = true, requiresDependencyResolution = ResolutionScope.TEST)
public class MyMojo extends AbstractMojo {
@Parameter(defaultValue = "${project}", readonly = true, required = true)
private MavenProject project;
@Parameter(defaultValue = "${session}", readonly = true, required = true)
private MavenSession session;
@Parameter(property = "reactorProjects", required = true, readonly = true)
private List<MavenProject> reactorProjects;
public void execute() throws MojoExecutionException, MojoFailureException {
MavenProject packagedProject = getWarProject(reactorProjects);
for (Artifact artifact : packagedProject.getArtifacts()) {
getLog().info(artifact.toString());
}
}
private MavenProject getWarProject(List<MavenProject> list) throws MojoExecutionException {
for (MavenProject project : list) {
if ("war".equals(project.getPackaging())) {
return project;
}
}
throw new MojoExecutionException("No WAR project found in the reactor");
}
}
Run Code Online (Sandbox Code Playgroud)
这样做是因为它使用注入的参数获取反应堆中的所有项目reactorProjects.然后,它"war"通过比较它们的包装来循环找到那些中的哪一个.找到后,getArtifacts()将返回该项目的所有已解析工件.
使其有效的神奇之处在于aggregator = trueMOJO定义:
标记此Mojo以多模块方式运行它,即使用列为模块的项目集合来构建构建.
添加到corePOM时
<plugin>
<groupId>sample.plugin</groupId>
<artifactId>test-maven-plugin</artifactId>
<version>1.0.0</version>
<executions>
<execution>
<id>test</id>
<phase>compile</phase>
<goals>
<goal>foo</goal>
</goals>
</execution>
</executions>
</plugin>
Run Code Online (Sandbox Code Playgroud)
并在您的示例项目中运行,这将在控制台中打印:
[INFO] commons-logging:commons-logging:jar:1.1.1:compile
[INFO] com.github:core:jar:0.1-SNAPSHOT:compile
[INFO] axis:axis:jar:1.4:compile
[INFO] org.apache.axis:axis-jaxrpc:jar:1.4:compile
[INFO] org.apache.axis:axis-saaj:jar:1.4:compile
[INFO] axis:axis-wsdl4j:jar:1.5.1:runtime
[INFO] commons-discovery:commons-discovery:jar:0.2:runtime
Run Code Online (Sandbox Code Playgroud)
这很好.有了它,我们可以继续前进,例如,比较正在构建的当前项目和打包项目的已解析工件.如果我们添加一个方法
private void printConflictingArtifacts(Set<Artifact> packaged, Set<Artifact> current) {
for (Artifact a1 : current) {
for (Artifact a2 : packaged) {
if (a1.getGroupId().equals(a2.getGroupId()) &&
a1.getArtifactId().equals(a2.getArtifactId()) &&
!a1.getVersion().equals(a2.getVersion())) {
getLog().warn("Conflicting dependency: " + a2 + " will be packaged and found " + a1);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
打电话给
printConflictingArtifacts(packagedProject.getArtifacts(), project.getArtifacts());
Run Code Online (Sandbox Code Playgroud)
将当前工件与打包项目的工件进行比较,并且仅保留具有相同组/工件ID但版本不同的工件,我们可以使用您的示例获取控制台输出:
[WARNING] Conflicting dependency: commons-logging:commons-logging:jar:1.1.1:compile will be packaged and found commons-logging:commons-logging:jar:1.0.4:runtime
Run Code Online (Sandbox Code Playgroud)
以上假设我们的最终包装模块是WAR模块.我们可以使它更通用,并让用户指定哪个模块是目标模块(即将打包实际交付).
为此,我们可以为MOJO添加一个参数
@Parameter(property = "packagingArtifact")
private String packagingArtifact;
Run Code Online (Sandbox Code Playgroud)
此参数将是表单groupId:artifactId,并将表示目标模块的坐标.然后我们可以添加一个方法,getPackagingProject其目标是返回MavenProject与这些坐标相关联的方法.
内部插件的配置core是
<plugin>
<groupId>sample.plugin</groupId>
<artifactId>test-maven-plugin</artifactId>
<version>1.0.0</version>
<executions>
<execution>
<id>test</id>
<phase>compile</phase>
<goals>
<goal>foo</goal>
</goals>
<configuration>
<packagingArtifact>com.github:web</packagingArtifact>
</configuration>
</execution>
</executions>
</plugin>
Run Code Online (Sandbox Code Playgroud)
完整的MOJO将是:
@Mojo(name = "foo", aggregator = true, requiresDependencyResolution = ResolutionScope.TEST, defaultPhase = LifecyclePhase.COMPILE)
public class MyMojo extends AbstractMojo {
@Parameter(defaultValue = "${project}", readonly = true, required = true)
private MavenProject project;
@Parameter(defaultValue = "${session}", readonly = true, required = true)
private MavenSession session;
@Parameter(property = "reactorProjects", required = true, readonly = true)
private List<MavenProject> reactorProjects;
@Parameter(property = "packagingArtifact")
private String packagingArtifact;
public void execute() throws MojoExecutionException, MojoFailureException {
MavenProject packagedProject = getPackagingProject(reactorProjects, packagingArtifact);
printConflictingArtifacts(packagedProject.getArtifacts(), project.getArtifacts());
}
private void printConflictingArtifacts(Set<Artifact> packaged, Set<Artifact> current) {
for (Artifact a1 : current) {
for (Artifact a2 : packaged) {
if (a1.getGroupId().equals(a2.getGroupId()) && a1.getArtifactId().equals(a2.getArtifactId())
&& !a1.getVersion().equals(a2.getVersion())) {
getLog().warn("Conflicting dependency: " + a2 + " will be packaged and found " + a1);
}
}
}
}
private MavenProject getPackagingProject(List<MavenProject> list, String artifact) throws MojoExecutionException {
if (artifact == null) {
return getWarProject(list);
}
String[] tokens = artifact.split(":");
for (MavenProject project : list) {
if (project.getGroupId().equals(tokens[0]) && project.getArtifactId().equals(tokens[1])) {
return project;
}
}
throw new MojoExecutionException("No " + artifact + " project found in the reactor");
}
private MavenProject getWarProject(List<MavenProject> list) throws MojoExecutionException {
for (MavenProject project : list) {
if ("war".equals(project.getPackaging())) {
return project;
}
}
throw new MojoExecutionException("No WAR project found in the reactor");
}
}
Run Code Online (Sandbox Code Playgroud)
这实现了上述思想:当用户给出目标模块时,我们将其用作参考.当此参数不存在时,我们默认在reactor中找到WAR.
| 归档时间: |
|
| 查看次数: |
653 次 |
| 最近记录: |