跨不同的Maven插件共享配置

时间:2017-12-22 11:08:04

标签: maven plugins configuration

我有两个Maven插件,AB。它们是独立开发的,但它们恰好需要相同的配置选项。大多数潜在用户都会安装插件A,插件B是其中的补充。

我正在尝试寻找一种在插件之间共享配置的方法。我知道您可以将配置选项提升为属性,然后为每个插件重复使用它们,但这仍然需要用户为每个插件的每个选项配置一个配置条目,这是一种样板文件。

这个问题的目标是找到一种跨插件共享配置的方法,从而减少可能的冗余。这可能吗?

1 个答案:

答案 0 :(得分:1)

起初,我认为这是不可能的,但通过深入研究Maven的内部,我意识到有一个解决方案。这个解决方案很简单 - 我们不必自己重新实现部分Maven内部,我们可以重用底层API。

解决方案

诀窍是使用Maven内部来修改需要配置另一个Mojo的Mojo的配置(在这种情况下,B需要来自A的配置)。

为此,首先我们需要为B设置一个mojo定义,其中包含parameter接受的所有配置值(A s)。然后,我们将在B中定义以下四个额外字段(如果它们尚未在A中定义),因为它们将是实际实现所必需的:

@Mojo(name = "B", requiresProject = true) // and the rest of the config
public class B extends AbstractMojo {
    @Parameter(defaultValue = "${project}", readonly = true, required = true)
    private MavenProject project;

    @Parameter(defaultValue = "${session}", readonly = true, required = true)
    private MavenSession session;

    @Parameter(defaultValue = "${mojoExecution}", readonly = true, required = true)
    private MojoExecution mojoExecution;

    @Component
    private MavenPluginManager mavenPluginManager;

    // and the rest of the properties here...

    public void execute() throws MojoExecutionException {
        B initializedMojo = ScalaImplementation.apply(project, session, mojoExecution, mavenPluginManager, encoding);
        // Implement plugin logic with `initializedMojo` instead of `this`.
    }
}

有了这四个新字段,我们可以通过以下方式实现ScalaImplementation(我选择在Scala代码中实现它):

object ScalaImplementation {
  def apply(project: MavenProject,
            session: MavenSession,
            mojoExecution: MojoExecution,
            mavenPluginManager: MavenPluginManager): B = {
    val currentConfig = mojoExecution.getConfiguration()
    val pluginA = Option(project.getBuild().getPluginsAsMap().get("groupIdA:artifactIdA"))
      .getOrElse(sys.error(s"Plugin A could not be found."))
    val configA = pluginA.getConfiguration().asInstanceOf[Xpp3Dom]
    mojoExecution.setConfiguration(Xpp3Dom.mergeXpp3Dom(currentConfig, configA))
    val initializedMojoB = mavenPluginManager
      .getConfiguredMojo(classOf[Mojo], session, mojoExecution)
      .asInstanceOf[B] // Note that this is safe.
    initializedMojoB
  }
}

请注意,要使此解决方案正常工作,mojo B必须没有任何其他必需字段,该字段不在A中且没有默认值(否则Maven会抱怨它无法将其初始化为null)。

摘要

我们所做的是通过组合插件A和插件B的配置来欺骗Maven mojo引擎,这些配置可在运行时访问。首先,我们得到了一个半初始化的mojo,只有我们关心的字段。然后我们将它传递给一个相对简单的方法,该方法负责设置当前mojoExecution的配置,并且我们实例化了一个新的mojo B。由于此新mojo具有AB的配置值,因此此时间已完全初始化并可以使用。