java - 使用 XmlPlexusConfiguration 为 bean 样式的 Maven 扩展导入更多配置

标签 java maven configuration plexus

我有一个 Maven 扩展,我已将其设置为从 POM 配置对象进行配置

<configuration>
  <foo>...</foo>
  <bar>...</bar>
</configuration>

结束调用

setFoo(...);
setBar(...);

方法。

我想允许配置导入额外配置以允许提议和第二种委托(delegate)方式,所以

<configuration>
  <import>g:a:v</import>
  <bar>...</bar>
</configuration>

其中 Artifact g:a:v 有一个文件 META-INF/my-project-name.xml 其内容为 <configuration><foo>...</foo></configuration> .

我想要 <configuration> 的组合使用导入和该 XML 文件生成与上面相同的对 setter 的调用。


使用

import org.codehaus.plexus.component.configurator.ComponentConfigurator;
import org.codehaus.plexus.configuration.PlexusConfiguration;
import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.codehaus.plexus.util.xml.Xpp3DomBuilder;

<dependency>
  <groupId>org.codehaus.plexus</groupId>
  <artifactId>plexus-container-default</artifactId>
  <version>1.6</version>
</dependency>
<dependency>
  <groupId>org.codehaus.plexus</groupId>
  <artifactId>plexus-classworlds</artifactId>
  <version>2.5.2</version>
</dependency>

我编写了以下代码来尝试从 XML 文件解析配置,然后调用配置器来配置我的 Maven 扩展。

{
  PlexusConfiguration configuration;
  try {
    configuration = loadConfiguration(
        log, cr.get(), EXTRA_CONFIGURATION_XML_RELATIVE_PATH);
  } catch (IOException ex) {
    throw new EnforcerRuleException(
        "Failed to load " + EXTRA_CONFIGURATION_XML_RELATIVE_PATH
        + " from " + artifactId, ex);
  }

  // TODO: is this right.
  // Newer versions have a MavenProject.getClassRealm() says
  // """
  // Warning: This is an internal utility method that is only public for
  // technical reasons, it is not part of the public API. In particular,
  // this method can be changed or deleted without prior notice and must
  // not be used by plugins.
  // """
  ClassRealm realm = null;

  try {
    configurator.configureComponent(configurable, configuration, realm);
  } catch (ComponentConfigurationException ex) {
    throw new EnforcerRuleException(
        "Failed to process configuration "
        + EXTRA_CONFIGURATION_XML_RELATIVE_PATH
        + " from " + artifactId,
        ex);
  }
}

哪里configurable只是 Object与二传手和 configuration是一个 XmlPlexusConfiguration这样加载:

static XmlPlexusConfiguration loadConfiguration(
    Log log,
    ClassRoot cr,
    String path)
throws EnforcerRuleException, IOException {
  log.debug("Loading " + path + " from " + cr.art.getId());
  File classRootFile = cr.classRoot;
  if (classRootFile == null) {
    throw new EnforcerRuleException(
        "Cannot import configuration from unresolved artifact "
        + art.getId());
  }
  Xpp3Dom dom = cr.readRelativePath(
      path,
      new ClassRoot.IOConsumer<InputStream, Xpp3Dom>() {
        public Xpp3Dom read(InputStream is) throws IOException {
          try {
            return Xpp3DomBuilder.build(is, "UTF-8", true);
          } catch (XmlPullParserException ex) {
            throw new IOException("Malformed XML", ex);
          } finally {
            is.close();
          }
        }
      });
  return new XmlPlexusConfiguration(dom);
}

我获得了 ComponentConfigurator通过

  configurator = (ComponentConfigurator) helper.getComponent(
      ComponentConfigurator.class);

当我运行它时,我得到了,

org.codehaus.plexus.component.configurator.ComponentConfigurationException:
Component does not implement interface org.codehaus.plexus.component.MapOrientedComponent
    at org.codehaus.plexus.component.configurator.MapOrientedComponentConfigurator.configureComponent(MapOrientedComponentConfigurator.java:41)
    at org.codehaus.plexus.component.configurator.AbstractComponentConfigurator.configureComponent(AbstractComponentConfigurator.java:44)
    at org.codehaus.plexus.component.configurator.AbstractComponentConfigurator.configureComponent(AbstractComponentConfigurator.java:37)
    at com.google.security.fences.ConfigurationImport.configure(ConfigurationImport.java:70)
    at com.google.security.fences.FencesMavenEnforcerRule.execute(FencesMavenEnforcerRule.java:146)
    at org.apache.maven.plugins.enforcer.EnforceMojo.execute(EnforceMojo.java:193)

是否有某种方法可以桥接 MapOrientedComponents 和用于配置我的扩展的 bean 样式反射 setter 调用?

或者是否有更好的方法将 XML 文件的文本转换为额外的配置操作?


编辑:

经过更多的挖掘,它看起来像

configurator = (ComponentConfigurator) helper.getComponent(
    ComponentConfigurator.class);

返回 MapOrientedComponentConfigurator当我通过集成测试运行它时 Verifier导致失败,但当我不这样做时,它会产生一种不同且兼容的配置器。

100% 可重复的区别在于我是否使用 -X 运行或不使记录器产生调试跟踪。

最佳答案

我不知道根本原因,但我知道

  1. 当使用 -X 运行以打开调试时,helper.getComponent(ComponentConfigurator.class) 返回一个 BasicComponentConfigurator 并且一切正常。
  2. 在没有 -X 的情况下运行时,相同的调用会返回一个 MapOrientedComponentConfigurator,因为它只能配置 MapOrientedComponent
  3. 将调用替换为 new BasicComponentConfigurator() 即可。
  4. 围绕依赖注入(inject)工作让我感到肮脏。

我最好的猜测是,根据是否请求调试跟踪,某些东西正在某个范围内创建组件配置器,而不是自行清理。


https://github.com/mikesamuel/fences-maven-enforcer-rule/commit/7cab8d8bd873f2341acab088e5bdad9c3e35640b是“修复”此行为的提交。

关于java - 使用 XmlPlexusConfiguration 为 bean 样式的 Maven 扩展导入更多配置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35919157/

相关文章:

java - Eclipse 构建路径/JBoss AS7 类加载异常问题

java - java8 Stream的filter()和map()方法是否使用迭代?

java - 如何使用 Maven 3 将 "exclude"依赖项嵌入到 uber-jar 中?

maven - 在不下载的情况下确定远程仓库中是否存在 Artifact

java - Haproxy 错误网关 502

java - 测试没有运行

maven - 将 Keycloak 集成到 Play2 项目中

Eclipse CDT 构建配置 - 一次构建全部

c++ - C++ Rhel confd cdb_get以奇怪的顺序返回元素

Python - 使用正则表达式解析 apache 配置