Maven 插件 - 将参数传递给生命周期阶段

Maven plugin - pass parameters to a lifecycle phase

我们有一个自定义的 Maven 插件,可以为我们的项目生成一些代码工件。该插件已经像这样配置了生命周期,'generate-resources' 阶段调用我们的自定义 class。

<?xml version="1.0" encoding="UTF-8"?>
<component-set>
    <components>
        <component>
            <role>org.apache.maven.lifecycle.mapping.LifecycleMapping</role>
            <role-hint>zip</role-hint>
            <implementation>org.apache.maven.lifecycle.mapping.DefaultLifecycleMapping</implementation>
            <configuration>
                <phases>
                    <generate-resources>com.b.e:productconfig-maven-plugin:generate</generate-resources>
                    <package>com.b.e:productconfig-maven-plugin:zip</package>
                    <install>org.apache.maven.plugins:maven-install-plugin:install</install>
                    <deploy>org.apache.maven.plugins:maven-deploy-plugin:deploy</deploy>
                </phases>
            </configuration>
        </component>
    </components>
</component-set>

我们对 运行 这个 'generate-resources' 阶段提出了新要求,参数略有不同。我曾希望我们可以定义第二阶段并传入像这样的 mojo 自定义属性

<?xml version="1.0" encoding="UTF-8"?>
<component-set>
    <components>
        <component>
            <role>org.apache.maven.lifecycle.mapping.LifecycleMapping</role>
            <role-hint>zip</role-hint>
            <implementation>org.apache.maven.lifecycle.mapping.DefaultLifecycleMapping</implementation>
            <configuration>
                <phases>
                    <generate-resources>com.b.e:productconfig-maven-plugin:generate -Dmojo.param=A</generate-resources>
                    <generate-resources>com.b.e:productconfig-maven-plugin:generate -Dmojo.param=B</generate-resources>
                    <package>com.b.e:productconfig-maven-plugin:zip</package>
                    <install>org.apache.maven.plugins:maven-install-plugin:install</install>
                    <deploy>org.apache.maven.plugins:maven-deploy-plugin:deploy</deploy>
                </phases>
            </configuration>
        </component>
    </components>
</component-set>

但这会引发此错误。

[ERROR] Could not find goal 'generate -Dmojo.param=A' in plugin com.b.e:productconfig-maven-plugin:1.0.6-SNAPSHOT among available goals generate, zip -> [Help 1]
org.apache.maven.plugin.MojoNotFoundException: Could not find goal 'generate -DoutputFileBaseDir=/home/poc/b/product_configuration/productconfig-maven-plugin/target/generated/delta' in plugin com.b.e:productconfig-maven-plugin:1.0.6-SNAPSHOT among available goals export, generate
    at org.apache.maven.plugin.internal.DefaultMavenPluginManager.getMojoDescriptor(DefaultMavenPluginManager.java:267)
    at org.apache.maven.plugin.DefaultBuildPluginManager.getMojoDescriptor(DefaultBuildPluginManager.java:185)
    at org.apache.maven.lifecycle.internal.DefaultLifecycleExecutionPlanCalculator.setupMojoExecution(DefaultLifecycleExecutionPlanCalculator.java:152)
    at org.apache.maven.lifecycle.internal.DefaultLifecycleExecutionPlanCalculator.setupMojoExecutions(DefaultLifecycleExecutionPlanCalculator.java:139)
    at org.apache.maven.lifecycle.internal.DefaultLifecycleExecutionPlanCalculator.calculateExecutionPlan(DefaultLifecycleExecutionPlanCalculator.java:116)
    at org.apache.maven.lifecycle.internal.DefaultLifecycleExecutionPlanCalculator.calculateExecutionPlan(DefaultLifecycleExecutionPlanCalculator.java:129)
    at org.apache.maven.lifecycle.internal.BuilderCommon.resolveBuildPlan(BuilderCommon.java:92)

有人知道将参数正确传递到生命周期阶段的方法吗?

有两个题目要求基本相同,none个答案:

  • Providing configuration for existing plugins in maven lifecycle mapping
  • Change default mojo configuration in lifecycle mapping

我很确定这个 "lifecycle mapping with property/parameter definition" 不会起作用。

component.xml 中的声明指定哪个目标绑定到生命周期的某个阶段,a.k.a。 生命周期映射。换句话说,根据我的理解:

  • 这是关于如果在构建过程中通过一个阶段运行执行什么
  • 不是关于如何完成的。

None 个参考文献:

提到:

  1. 将多个目标绑定到一个阶段。

    因为 DefaultLifecycleMapping.getPhases(...) returns a Map 其中键表示阶段,这根本不可能。

  2. 具有 property/parameter 定义的目标到阶段绑定。

    您的错误消息的 Could not find goal 'generate -Dmojo.param=A' 部分告诉我 goal 部分的完整字符串被视为目标名称,没有应用进一步的参数提取。

  1. 对于Binding more than one goal to a phase:

    您可以在目标之间放置一个逗号,这当然适用于 Maven 3.6.1,但我不能说这是否是一个新功能。即:

    <package>org.apache.maven.plugins:maven-jar-plugin:jar,org.expath.pkg:expath-pkg-maven-plugin:pkg</package>
    
  2. 对于A goal-to-phase binding with a property/parameter definition:

    我能够以编程方式完成您的要求。

    对于我的插件,我希望能够选择先编译 Java 类 并将其放入 Jar 中,但最终的包格式是 Xar,将其视为包装器,它将包含 Jar 和其他东西。

    我没有使用 components.xml 中的 DefaultLifecycleMapping,而是创建了自己的 LifecycleMapping 组件,它指定了默认生命周期,并且从那里我能够设置配置(对于我的 use-case) Jar 插件。

    我的自定义生命周期组件:

    @Component(role = LifecycleMapping.class, hint = "xar", description = "EXPath Pkg Lifecycle Mapping")
    public class PkgLifecycleMapping implements LifecycleMapping {
    
        private final Map<String, Lifecycle> lifecycleMap = new HashMap<>();
    
        public PkgLifecycleMapping() {
            final Map<String, LifecyclePhase> phases = new HashMap<>();
            phases.put("process-resources", new LifecyclePhase("org.apache.maven.plugins:maven-resources-plugin:resources"));
            phases.put("compile", new LifecyclePhase("org.apache.maven.plugins:maven-compiler-plugin:compile"));
    
            final LifecyclePhase packageLifecyclePhase = new LifecyclePhase("org.apache.maven.plugins:maven-jar-plugin:jar,org.expath.pkg:expath-pkg-maven-plugin:pkg");
    
            // configure the maven-jar-plugin mojo
            final LifecycleMojo jarLifecyclePhase = packageLifecyclePhase.getMojos().get(0);
            Xpp3Dom config = jarLifecyclePhase.getConfiguration();
            if (config == null) {
                config =  new Xpp3Dom("configuration");
            }
            final Xpp3Dom skipIfEmpty = new Xpp3Dom("skipIfEmpty");
            skipIfEmpty.setValue("true");
            config.addChild(skipIfEmpty);
            jarLifecyclePhase.setConfiguration(config);
    
            phases.put("package", packageLifecyclePhase);
    
            phases.put("install", new LifecyclePhase("org.apache.maven.plugins:maven-install-plugin:install"));
            phases.put("deploy", new LifecyclePhase("org.apache.maven.plugins:maven-deploy-plugin:deploy"));
    
            final Lifecycle lifecycle = new Lifecycle();
            lifecycle.setId("default");
            lifecycle.setLifecyclePhases( phases );
    
            lifecycleMap.put("default", lifecycle );
        }
    
        @Override
        public Map<String, Lifecycle> getLifecycles() {
            return lifecycleMap;
        }
    
        @Override
        @Deprecated
        public List<String> getOptionalMojos(final String lifecycle) {
            return null;
        }
    
        @Override
        @Deprecated
        public Map<String, String> getPhases(final String lifecycle) {
            final Lifecycle lifecycleMapping = lifecycleMap.get(lifecycle);
            if (lifecycleMapping != null) {
                return LifecyclePhase.toLegacyMap(lifecycleMapping.getLifecyclePhases());
            } else {
                return null;
            }
        }
    }
    

    您还需要将 plexus 元数据插件添加到 pom.xml 中的构建插件中:

        <plugin>
            <groupId>org.codehaus.plexus</groupId>
            <artifactId>plexus-component-metadata</artifactId>
            <version>2.0.0</version>
            <executions>
                <execution>
                    <goals>
                        <goal>generate-metadata</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    

    我的 src/main/resources/META-INF/plexus/components.xml 看起来像:

    <component-set>
        <components>
            <component>
                <role>org.apache.maven.artifact.handler.ArtifactHandler</role>
                <role-hint>xar</role-hint>
    <implementation>org.apache.maven.artifact.handler.DefaultArtifactHandler</implementation>
                <configuration>
                    <type>xar</type>
                    <extension>xar</extension>
                    <packaging>xar</packaging>
                </configuration>
            </component>
        </components>
    </component-set>
    

    构建后我生成的 target/classes/META-INF/plexus/components.xml 看起来像:

    <component-set>
        <components>
            <component>
                <role>org.apache.maven.artifact.handler.ArtifactHandler</role>
                <role-hint>xar</role-hint>
                <implementation>org.apache.maven.artifact.handler.DefaultArtifactHandler</implementation>
                <configuration>
                    <type>xar</type>
                    <extension>xar</extension>
                    <packaging>xar</packaging>
                </configuration>
            </component>
            <component>
              <role>org.apache.maven.lifecycle.mapping.LifecycleMapping</role>
              <role-hint>xar</role-hint>
              <implementation>org.expath.pkg.maven.PkgLifecycleMapping</implementation>
              <description>EXPath Pkg Lifecycle Mapping</description>
              <isolated-realm>false</isolated-realm>
            </component>
        </components>
    </component-set>