![](/img/trans.png)
[英]In Gradle, how can I generate a POM file with dynamic dependencies resolved to the actual version used?
[英]How do I obtain a fully resolved Model of a pom file?
如何获得pom文件的完全解析模型?
这基本上是对我如何以编程方式构建有效的pom文件模型的重新描述?
我正在构建一个对一组模块执行一些验证规则的Maven插件。 这些模块的pom文件可用,但是在执行插件时它们不是反应堆的一部分。
我可以使用此方法读取pom文件并获取相应的Model对象(为简单起见,删除了异常处理):
private Model pomToModel(String pathToPom) throws Exception {
BufferedReader in = new BufferedReader(new FileReader(pathToPom));
MavenXpp3Reader reader = new MavenXpp3Reader();
Model model = reader.read(in);
return model;
}
它可以工作,但是Model对象仅具有与pom文件相同的信息。
如何改进该方法,以便可以获得“完全解析”的Model对象? 通过完全解决,我的意思是:具有所有传递依赖项以及父poms的所有其他项。
干杯!
我做的 :-)
help:有效的pom和依赖关系:tree根本没有帮助。
我必须看一下maven如何为注入到mojo中的MavenProject构建模型。 help:effective-pom已经收到了解析的模型,并且dependency:tree只建立了一个DependencyGraph,但没有将整个pom模型加载到内存中。
通过使用下面的代码,我能够从父级获得所有信息的Model对象,并带有解析的$ {property}表达式和扩展的传递依赖项。
这是如何做:
1)获取一个ModelResolver
您将需要接口org.apache.maven.model.resolution.ModelResolver的实例。 不幸的是,maven无法通过依赖注入轻松地提供一个(至少我找不到一个),因此我们必须构建一个。 为了使事情变得更好,该接口的仅有两个实现受到包保护,因此您需要使用一些反射魔术来实例化它。 实现它的具体类是DefaultModelResolver和ProjectModelResolver 。 我能够建立像这样的DefaultModelResolver
/**
* The Maven Project Object
*
* @parameter expression="${project}"
* @required2.0
* @readonly
*/
protected MavenProject project;
/**
* @component
*/
protected ArtifactResolver artifactResolver;
/**
* @component
*/
protected RemoteRepositoryManager remoteRepositoryManager;
private Object invoke( Object object, String method )
throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
return object.getClass().getMethod( method ).invoke( object );
}
private org.apache.maven.model.resolution.ModelResolver makeModelResolver() throws MojoExecutionException {
try {
ProjectBuildingRequest projectBuildingRequest =
(ProjectBuildingRequest) invoke( project, "getProjectBuildingRequest" );
Class c = Class.forName("org.apache.maven.repository.internal.DefaultModelResolver");
Constructor ct = c.getConstructor(new Class[]{RepositorySystemSession.class,
RequestTrace.class, String.class,
ArtifactResolver.class, RemoteRepositoryManager.class,
List.class});
ct.setAccessible(true);
return (org.apache.maven.model.resolution.ModelResolver) ct.newInstance(new Object[]{
projectBuildingRequest.getRepositorySession(),
null, null, artifactResolver, remoteRepositoryManager,
project.getRemoteProjectRepositories()});
} catch (Exception e) {
throw new MojoExecutionException("Error instantiating DefaultModelResolver", e);
}
}
2)建立模型
当您拥有modelResolver时,您可以像这样从pom文件构建模型:
public Model resolveEffectiveModel(File pomfile) {
try {
return modelBuilder.build(makeModelBuildRequest(pomfile)).getEffectiveModel();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private ModelBuildingRequest makeModelBuildRequest(File artifactFile) {
DefaultModelBuildingRequest mbr = new DefaultModelBuildingRequest();
mbr.setPomFile(artifactFile);
mbr.setModelResolver(modelResolver); // <-- the hard-to-get modelResolver
return mbr;
}
看起来不漂亮,但是对我有用。.:P
罗曼(Romain)提供了上面的很好的答案,但是它使用了从maven 3.x中删除的不赞成使用的类。
@Parameter( defaultValue = "${project}", readonly = true )
private MavenProject project;
@Component
private RepositorySystem repositorySystem;
@Component
private ProjectBuilder mavenProjectBuilder;
@Parameter( defaultValue = "${session}", readonly = true )
private MavenSession session;
private MavenProject getMavenProject(String groupId, String artifactId, String version) throws ProjectBuildingException {
Artifact pomArtifact = repositorySystem.createProjectArtifact(groupId, artifactId, version);
ProjectBuildingResult build = mavenProjectBuilder.build(pomArtifact, session.getProjectBuildingRequest());
return build.getProject();
}
一个工作示例在hierarchy-maven-plugin中
也许对您来说太迟了,但是如果将来可以帮助其他人。 所以我这样做是这样的:
@Component
private RepositorySystem repositorySystem;
@Component
private MavenProjectBuilder mavenProjectBuilder;
@Parameter(property = "project.remoteArtifactRepositories")
protected List<ArtifactRepository> remoteRepositories;
@Parameter(property = "localRepository")
protected ArtifactRepository localRepository;
...
Artifact pomArtifact = repositorySystem.createProjectArtifact(groupId, artifactId,version);
MavenProject project = mavenProjectBuilder.buildFromRepository(pomArtifact
, remoteRepositories, localRepository);
就是这样。 它应该工作。 如果您有一些特殊的包装(例如捆绑包...),请在目标pom项目中确保与这些包装关联的插件已安装在当前项目中。
您寻找的源代码在help:effective-pom
。
-编辑更新-
快速浏览之后,您似乎需要根据读取的pom构建一个Maven Project
。 这可能涉及许多步骤,包括解析POM的父项目,下载和解析其他Maven插件工件以及将所有引用连接在一起。
仅阅读儿童级别的pom不会做到这一点。
当执行“ mvn help:effective-pom”时,maven帮助插件会执行类似的操作。
我认为这不会显示传递性的缺点。
mvndependency:tree目标可以做到: http : //svn.apache.org/viewvc/maven/plugins/tags/maven-dependency-plugin-2.4/src/main/java/org/apache/maven/plugin/dependency /TreeMojo.java?view=markup
也许您可以同时创建两者?
万一有人想要它,下面是在Groovy中运行的示例。 它使用Grape来动态加载消耗pom.xml所需的依赖关系。 它同时加载运行时类路径和测试类路径。
@Grapes([
@Grab(group='org.apache.maven', module='maven-core', version='3.0.5'),
@Grab(group='org.apache.maven', module='maven-compat', version='3.0.5'),
@Grab(group='com.jcabi', module='jcabi-aether', version='0.10.1')
])
// http://www.programcreek.com/java-api-examples/index.php?api=org.apache.maven.project.MavenProjectBuilder See # 20
import org.codehaus.plexus.DefaultPlexusContainer
import org.apache.maven.project.MavenProjectBuilder
import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.project.DefaultProjectBuilderConfiguration
import org.apache.maven.artifact.repository.DefaultArtifactRepository
import com.jcabi.aether.Aether
import org.sonatype.aether.repository.RemoteRepository;
import org.sonatype.aether.util.artifact.DefaultArtifact;
import org.sonatype.aether.artifact.Artifact;
container=new DefaultPlexusContainer();
projectBuilder=(MavenProjectBuilder)container.lookup(MavenProjectBuilder.class.getName());
layout=(ArtifactRepositoryLayout)container.lookup(ArtifactRepositoryLayout.class.getName(),"default");
def projectInfo(localRepoUrl, pom){
File pomFile = new File(pom);
String localRepoUrl2 = "file://" + localRepoUrl;
File local = new File(localRepoUrl);
ArtifactRepository localRepo=new DefaultArtifactRepository("local",localRepoUrl2,layout);
pbConfig=new DefaultProjectBuilderConfiguration().setLocalRepository(localRepo);
project = projectBuilder.build( pomFile, pbConfig );
aether = new Aether(project, local);
[ runtime: resolveDependencies(aether, project, "runtime"),
test : resolveDependencies(aether, project, "test") ];
}
def resolveDependencies (aether, project, scope) {
depLists = project.getDependencies().collect {
art = new DefaultArtifact(it.getGroupId(), it.getArtifactId(), it.getClassifier(), it.getType(),
it.getVersion());
Collection<Artifact> deps = aether.resolve( art, scope );
deps.collect{ it.getFile().getAbsolutePath() }
}
[ dependencies : depLists.collect {it.first()}, classpath : depLists.flatten() ]
}
println projectInfo("c:/Users/lpmsmith/.m2/repository", "pom.xml");
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.