使用地图的地图作为 Maven 插件参数

2023-12-12

是否可以使用地图的地图作为 Maven 插件参数?

@Parameter
private Map<String, Map<String, String>> converters;

然后像这样使用它

<converters>
  <json>
     <indent>true</indent>
     <strict>true</strict>
  </json>
  <yaml>
      <stripComments>false</stripComments>
  </yaml>
<converters>

如果我像这样使用它,converters仅包含键json and yaml以 null 作为值。

我知道可以将复杂的对象作为值,但是是否也可以像本示例中那样使用映射作为变量元素值?


这显然是一个限制西丛Mojo API 内部使用的项目。如果你往里面看MapConverter源代码,您会发现它首先尝试通过尝试将配置解释为字符串(调用fromExpression),当失败时,查找值的预期类型。但是此方法不检查参数化类型,这就是我们这里的情况(因为地图值的类型是Map<String, String>)。我提交了错误 498757在该项目的 Bugzilla 上进行跟踪。

使用自定义包装对象

一种解决方法是不使用Map<String, String>作为值但使用自定义对象:

@Parameter
private Map<String, Converter> converters;

和一个班级Converter,与 Mojo 位于同一包中,为:

public class Converter {

    @Parameter
    private Map<String, String> properties;

    @Override
    public String toString() { return properties.toString(); } // to test

}

然后你可以配置你的 Mojo:

<converters>
  <json>
    <properties>
      <indent>true</indent>
      <strict>true</strict>
    </properties>
  </json>
  <yaml>
    <properties>
      <stripComments>false</stripComments>
    </properties>
  </yaml>
</converters>

此配置将正确地将值注入内部映射中。它还保留了可变方面:该对象仅作为内部映射的包装器引入。我用一个简单的测试魔力对此进行了测试

public void execute() throws MojoExecutionException, MojoFailureException {
    getLog().info(converters.toString());
}

输出是预期的{json={indent=true, strict=true}, yaml={stripComments=false}}.

使用自定义配置器

我还找到了一种方法来保持Map<String, Map<String, String>>通过使用自定义ComponentConfigurator.

所以我们想修复MapConverter通过继承它,麻烦的是如何注册这个新的FixedMapConverter。默认情况下,Maven 使用BasicComponentConfigurator配置 Mojo,它依赖于DefaultConverterLookup查找用于特定类的转换器。在这种情况下,我们想要提供一个自定义转换为Map这将返回我们的固定版本。因此,我们需要扩展这个基本配置器并注册我们的新转换器。

import org.codehaus.plexus.classworlds.realm.ClassRealm;
import org.codehaus.plexus.component.configurator.BasicComponentConfigurator;
import org.codehaus.plexus.component.configurator.ComponentConfigurationException;
import org.codehaus.plexus.component.configurator.ConfigurationListener;
import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
import org.codehaus.plexus.configuration.PlexusConfiguration;

public class CustomBasicComponentConfigurator extends BasicComponentConfigurator {
    @Override
    public void configureComponent(final Object component, final PlexusConfiguration configuration,
            final ExpressionEvaluator evaluator, final ClassRealm realm, final ConfigurationListener listener)
            throws ComponentConfigurationException {
        converterLookup.registerConverter(new FixedMapConverter());
        super.configureComponent(component, configuration, evaluator, realm, listener);
    }
}

然后我们需要告诉 Maven 使用这个新的配置器而不是基本的配置器。这是一个 2 步过程:

  1. 在 Maven 插件中,创建一个文件src/main/resources/META-INF/plexus/components.xml注册新组件:

    <?xml version="1.0" encoding="UTF-8"?>
    <component-set>
      <components>
        <component>
          <role>org.codehaus.plexus.component.configurator.ComponentConfigurator</role>
          <role-hint>custom-basic</role-hint>
          <implementation>package.to.CustomBasicComponentConfigurator</implementation>
        </component>
      </components>
    </component-set>
    

    请注意一些事项:我们声明一个具有提示的新组件"custom-basic",这将作为一个 id 来引用它,并且<implementation>指的是我们的配置器的完全限定类名。

  2. 告诉我们的 Mojo 使用此配置器configurator的属性@Mojo注解:

    @Mojo(name = "test", configurator = "custom-basic")
    

    这里传递的配置器对应于在components.xml above.

有了这样的设置,你终于可以声明了

@Parameter
private Map<String, Map<String, String>> converters;

并且所有内容都会正确注入:Maven 将使用我们的自定义配置器,它将注册我们的固定版本的地图转换器并正确转换内部地图。


完整代码FixedMapConverter(这几乎是复制粘贴MapConverter因为我们无法覆盖错误的方法):

public class FixedMapConverter extends MapConverter {

    public Object fromConfiguration(final ConverterLookup lookup, final PlexusConfiguration configuration,
            final Class<?> type, final Type[] typeArguments, final Class<?> enclosingType, final ClassLoader loader,
            final ExpressionEvaluator evaluator, final ConfigurationListener listener)
            throws ComponentConfigurationException {
        final Object value = fromExpression(configuration, evaluator, type);
        if (null != value) {
            return value;
        }
        try {
            final Map<Object, Object> map = instantiateMap(configuration, type, loader);
            final Class<?> elementType = findElementType(typeArguments);
            if (Object.class == elementType || String.class == elementType) {
                for (int i = 0, size = configuration.getChildCount(); i < size; i++) {
                    final PlexusConfiguration element = configuration.getChild(i);
                    map.put(element.getName(), fromExpression(element, evaluator));
                }
                return map;
            }
            // handle maps with complex element types...
            final ConfigurationConverter converter = lookup.lookupConverterForType(elementType);
            for (int i = 0, size = configuration.getChildCount(); i < size; i++) {
                Object elementValue;
                final PlexusConfiguration element = configuration.getChild(i);
                try {
                    elementValue = converter.fromConfiguration(lookup, element, elementType, enclosingType, //
                            loader, evaluator, listener);
                }
                // TEMP: remove when http://jira.codehaus.org/browse/MSHADE-168
                // is fixed
                catch (final ComponentConfigurationException e) {
                    elementValue = fromExpression(element, evaluator);

                    Logs.warn("Map in " + enclosingType + " declares value type as: {} but saw: {} at runtime",
                            elementType, null != elementValue ? elementValue.getClass() : null);
                }
                // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                map.put(element.getName(), elementValue);
            }
            return map;
        } catch (final ComponentConfigurationException e) {
            if (null == e.getFailedConfiguration()) {
                e.setFailedConfiguration(configuration);
            }
            throw e;
        }
    }

    @SuppressWarnings("unchecked")
    private Map<Object, Object> instantiateMap(final PlexusConfiguration configuration, final Class<?> type,
            final ClassLoader loader) throws ComponentConfigurationException {
        final Class<?> implType = getClassForImplementationHint(type, configuration, loader);
        if (null == implType || Modifier.isAbstract(implType.getModifiers())) {
            return new TreeMap<Object, Object>();
        }

        final Object impl = instantiateObject(implType);
        failIfNotTypeCompatible(impl, type, configuration);
        return (Map<Object, Object>) impl;
    }

    private static Class<?> findElementType( final Type[] typeArguments )
    {
        if ( null != typeArguments && typeArguments.length > 1 )
        {
            if ( typeArguments[1] instanceof Class<?> )
            {
                return (Class<?>) typeArguments[1];
            }
            // begin fix here
            if ( typeArguments[1] instanceof ParameterizedType )
            {
                return (Class<?>) ((ParameterizedType) typeArguments[1]).getRawType();
            }
            // end fix here
        }
        return Object.class;
    }

}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用地图的地图作为 Maven 插件参数 的相关文章

随机推荐

  • 如何使用 MVVM 在 RibbonComboBox 上设置 SelectedItem?

    我该如何设置SelectedItem on a RibbonComboBox using MVVM图案 View
  • Playframework [1.2.7] 依赖项失败

    我们遇到了游戏框架依赖管理的问题 几天前该问题运行良好 我们尚未对依赖文件进行任何配置更改或更改 但在我们的构建服务器和本地 均位于不同的网络和 ISP 上 上均出现以下错误 problems summary WARNINGS module
  • Django 从 ImageField 下载图像

    我正在使用 Django 1 7 和 Python 3 4 我有一个这样的模型 class ImageModel models Model image models ImageField verbose name image upload
  • 两个数据库之间的Mysql数据库同步

    我们正在各个商店运行带有 MySql 后端的 Java PoS 销售点 应用程序 我想让商店中的数据库与主机服务器上的数据库保持同步 当商店发生一些变化时 它们应该在主机服务器上更新 我该如何实现这一目标 创建复制并不难 这里有一些很好的教
  • 在C中查询最大套接字发送缓冲区大小?

    我知道我可以 cat proc sys net core wmem max 来获取套接字上 SO SNDBUF 的最大大小 但是有没有一种简单的方法可以在 C 中查询该值 而无需执行打开文件的笨拙步骤 读取并转换为整数 要获取 net ip
  • 如何在 R 中查看所有 xml_nodeset 类对象(rvest::html_nodes 的输出)?

    如果我们创建一个类的对象xml nodes using rvest s html nodes 我们如何在 R 控制台中查看所有输出 Example library rvest library dplyr Generate some samp
  • PHP MySQL 多条件搜索

    我在网站中有一个搜索表单 希望有几个由用户输入的搜索词来执行数据库搜索 词如下 Keywords 物业出售 出售 出租 房产类型 公寓 排屋 State 最低价格 最高价格 这是使用上述术语的输入执行搜索的脚本 public functio
  • Supabase动态RPC函数

    我希望创建一个 RPC 来获取列的不同值 但我将在多个表中执行此操作 并且我不想为每个列和每个表一遍又一遍地编写此函数 我有以下 SQL 语句可以满足我的需要 SELECT owner FROM customers GROUP BY own
  • 多种语言的问题

    我希望我的应用程序能够提供多种语言版本 比如说两种 一种是默认英语 另一种是默认英语 这两个选项都可以在我的主页上找到 并且必须显示一个链接 使用户能够选择他选择的语言 我正在阅读Django官方文档为了这 所以任何人都可以让我知道如何做到
  • 为什么不打印!在 Rust 单元测试中工作?

    我已经实现了以下方法和单元测试 use std fs File use std path Path use std io prelude fn read file path Path let mut file File open path
  • 如何在matlab中将图像分割为64块

    我想计算每个图像的颜色布局描述符 CLD 该算法包括四个阶段 在第一阶段 我必须将每个图像划分为 64 个块 i 8 8 n 以便从每个块计算单个代表颜色 我尝试使用 For 循环 将图像划分为 64 个块 但我得到 64婷图像 我想获得具
  • 如何从双卡双待Android手机获取运营商名称?

    我可以从双 SIM 卡手机获取运营商名称 我使用了以下代码 但它仅适用于单 SIM 卡手机 TelephonyManager telephonyManager TelephonyManager mContext getSystemServi
  • << 运算符重写为 cout int 和 double 值

    我需要重写 我想我已经包含了所有必要的部分 提前致谢 struct Reading int hour double temperature Reading int h double t hour h temperature t bool o
  • '忽略' git rebase '他们的' 中的二进制文件

    我想从此走下去 A B C D E F G 其中 Branch1 指向 E Branch2 指向 G to this Branch1 A B C D E Branch2 F G 我希望 Branch2 始终 获胜 我已经做到了这一点 git
  • 安装 Ninject.MVC5 后出现 FileLoadException

    我正在尝试通过 Adam Freeman 的 Pro ASP NET MVC 5 书来学习 ASP NET MVC 不幸的是 所有使用 Ninject 的项目都会抛出相同的错误 Ninject dll 中发生 System IO FileL
  • 双击按钮

    如何添加双击按钮的操作 void buttonTouchDownRepeat id sender event UIEvent event UITouch touch event allTouches anyObject if touch t
  • java中的xml dom解析器? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 目前不接受答案 任何人都可以分享java中dom解析器的好文档吗 thanks 以下是在 java 中使用 DOM 的教程 xml dom DOM解析器 java
  • 你能解释一下为什么情节在 J 处停止(在索引 10 处)

    我正在运行这个程序来查找特定文本中的字符分布 this is a paragraph from python documentation mytext When a letter is first k encountered it is m
  • StoreKit 验证错误 21002:收据数据属性中的数据格式错误

    在 iPhone 4 iOS 4 设备上 沙箱 App Store 在验证过程中报告此错误 21002 收据数据属性中的数据格式错误 在 iPhone 5 iOS 6 设备上 相同的代码可以正常工作 状态 0 收据返回 没有任何问题 我已经
  • 使用地图的地图作为 Maven 插件参数

    是否可以使用地图的地图作为 Maven 插件参数 Parameter private Map