2

我需要阅读 Java 中的插件配置。我已经使用 aether 库来获取运行时依赖项、编译时依赖项等。但是我可以使用 aether 来读取基于 pom 文件的插件配置吗?

像这样的东西

<properties>
  <servicePort>8080</servicePort>
  <adminPort>8081</adminPort>
</properties>

<build>
  <plugins>
    <plugin>
      <groupId>com.company.group</groupId>
      <artifactId>my-plugin</artifactId>
      <version>0.1-SNAPSHOT</version>
      <configuration>
        <myConfig>
          <somePropName>someProp</somePropName>
          <portMappings>
            <someProp>${servicePort}</someProp>
            <someProp-admin>${adminPort}</someProp-admin>
          </portMappings>
        </myConfig>
      </configuration>
    </plugin>
  </plugins>
</build>

我希望能够解决

some-Prop 8080
some-prop-admin 8081 

从这个机制

目前我像这样获取编译关系依赖项

Dependency dependency = new Dependency(new DefaultArtifact(
                    coordinate), COMPILE);
CollectRequest collectRequest = new CollectRequest();
collectRequest.setRoot(dependency);

collectRequest.addRepository(this.aetherSession
        .getRemoteRepository());
DependencyNode node = this.aetherSession
        .getRepoSystem()
        .collectDependencies(this.aetherSession.getRepoSession(),
                collectRequest).getRoot();
DependencyRequest dependencyRequest = new DependencyRequest();
dependencyRequest.setRoot(node);
result = this.aetherSession
        .getRepoSystem()
        .resolveDependencies(this.aetherSession.getRepoSession(),
                dependencyRequest).getArtifactResults();
FinalResult.addAll(result);
4

1 回答 1

1

我不知道是否有更简单的方法,但是您可以使用 Aether API 来解析您感兴趣的 POM 工件,然后使用 Model Builder API 从中构建一个 Maven 模型。

首先,如果您的工件的坐标不是 POM 工件的坐标,您需要通过创建一个DefaultArtifact具有相同 GAV 但类型为"pom". 要解析工件,您可以resolveArtifact在存储库系统上调用,并使用getArtifact().

获得已解析的工件后,您可以使用maven-model-builder该工件的文件构建 Maven 模型。ModelBuilder可以使用工厂DefaultModelBuilderFactory.newInstance()方法创建。

对于具有父 POM 的工件,ModelResolver需要在请求中设置 a 以构建模型。但是,Aether 唯一可用的实现,即DefaultModelResolver,内部是包私有的,maven-aether-provider因此我们需要使用反射 API 来构造它。它需要注入由serviceLocator返回的组件来检索MavenRepositorySystemUtils.newServiceLocator()。这需要与构建 Aether 会话的定位器相同。

DefaultArtifact artifact = new DefaultArtifact(coordinate);
Artifact pomArtifact = new DefaultArtifact(artifact.getGroupId(), artifact.getArtifactId(), "pom", artifact.getVersion());

ArtifactRequest request = new ArtifactRequest(pomArtifact, Arrays.asList(aetherSession.getRemoteRepository()), null);
pomArtifact = aetherSession.getRepoSystem().resolveArtifact(session, request).getArtifact();

ModelBuilder modelBuilder = new DefaultModelBuilderFactory().newInstance();
ModelBuildingRequest buildingRequest = new DefaultModelBuildingRequest();
buildingRequest.setPomFile(pomArtifact.getFile());
buildingRequest.setProcessPlugins(true);
buildingRequest.setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL);

Constructor<?> constr = Class.forName("org.apache.maven.repository.internal.DefaultModelResolver").getConstructors()[0];
constr.setAccessible(true);
ModelResolver modelResolver = (ModelResolver) constr.newInstance(session, null, null,
        serviceLocator.getService(ArtifactResolver.class),
        serviceLocator.getService(VersionRangeResolver.class),
        serviceLocator.getService(RemoteRepositoryManager.class), request.getRepositories());
buildingRequest.setModelResolver(modelResolver);

Model model = modelBuilder.build(buildingRequest).getEffectiveModel();

Xpp3Dom pluginConfiguration = (Xpp3Dom) model.getBuild().getPluginsAsMap().get("com.company.group:my-plugin").getConfiguration();
Xpp3Dom myConfig = pluginConfiguration.getChild("myConfig");
System.out.println(myConfig.getChild("somePropName").getValue()); // prints "someProp"

默认情况下,模型构建器未配置为处理插件,因此我们需要调用setProcessPlugin(true). 获得有效模型后,配置将包含在一个Xpp3Dom对象中,您可以借助 导航该对象getChild(name),以获取命名的子 XML 元素,并getValue()获取 XML 元素的值。

于 2016-09-16T19:18:49.967 回答