【问题标题】:Share configuration across different Maven plugins在不同的 Maven 插件之间共享配置
【发布时间】:2017-12-22 11:08:04
【问题描述】:

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

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

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

【问题讨论】:

  • 首先你说的是什么插件?此外,如果用户需要通过默认用例配置很多东西,那么插件作者做错了什么......
  • A 是 Maven 的 Scala 插件,B 是我正在为 github.com/scalacenter/bloop 开发的插件,它需要来自 A 的配置数据才能创建配置文件用它。这与默认用例无关,而是我需要将 maven 配置转换为我自己的配置格式。配置字段的一对一映射。
  • @khmarbaise 我想我已经得到了答案,我会发布它,如果您认为它是正确的,请告诉我。

标签: maven plugins configuration


【解决方案1】:

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

解决方案

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

为此,首先我们需要为B 定义一个mojo 定义,其中包含A 接受的所有配置值(parameters)。然后,我们将在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 的配置值,所以这个时间已经完全初始化并可以使用了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-08
    • 2015-11-15
    • 1970-01-01
    • 2017-09-28
    • 1970-01-01
    • 2017-07-12
    • 1970-01-01
    • 2011-05-07
    相关资源
    最近更新 更多