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

时间:2016-03-10 14:25:26

标签: java maven configuration plexus

我有一个Maven扩展,我已经设置了从POM配置对象

配置
<configuration>
  <foo>...</foo>
  <bar>...</bar>
</configuration>

最终致电

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

方法

我想允许配置导入额外的配置以允许建议和第二种授权方式,所以

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

其中工件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只是带有setter的Objectconfiguration加载了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,但是当我不这样做时,它产生一个不同的&amp;兼容的配置器。

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

1 个答案:

答案 0 :(得分:1)

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

  1. $ brew unlink cairo Unlinking /usr/local/Cellar/cairo/1.14.2... 30 symlinks removed $ brew install cairo 一起运行以启用调试时,-X会返回helper.getComponent(ComponentConfigurator.class),一切正常。
  2. 在没有BasicComponentConfigurator的情况下运行时,同一个调用会返回-X个barf,因为它只能配置MapOrientedComponentConfigurator
  3. MapOrientedComponent取代该通话。
  4. 解决依赖注入让我觉得很脏。
  5. 我最好的猜测是,根据是否请求调试跟踪,有些东西在某个范围内创建了一个组件配置器,而不是自行清理。

    https://github.com/mikesamuel/fences-maven-enforcer-rule/commit/7cab8d8bd873f2341acab088e5bdad9c3e35640b是此行为被修复的提交。&#34;