我如何获得一个POM文件的完全解析模型?
这是基本的改述我怎样才能programmaticaly建立一个POM文件的有效模式?
我建立执行对一组模块的一些验证规则Maven插件。 这些模块的POM文件也有,但在执行时,插件,他们不是反应器的一部分。
我可以读取POM文件并获得使用该方法(除去异常处理为简单起见)相应的模型对象:
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文件具有相同的信息。
我怎样才能改善这种方法,这样我可以得到一个“完全解决”模型对象? 通过完全解决,我的意思是:与所有的传递依赖,一切都从父劲歌人。
干杯!
Answer 1:
我做的 :-)
帮助:有效,聚甲醛和依赖:树真的没有帮助的。
我不得不看行家如何建立为获取在魔力注入MavenProject模型。 帮助:有效-POM已经收到解决模式,以及依赖:树只建立一个DependencyGraph,但它不会加载整个模型的POM到内存中。
通过使用下面的代码,我能得到一个模型对象从父的所有信息,以解决$ {}属性表达式和扩展传递依赖。
这是如何做:
1)获取ModelResolver
您将需要接口org.apache.maven.model.resolution.ModelResolver的一个实例。 不幸的是,行家不提供一个通过依赖注入(至少我无法找到一个)容易,所以我们必须建立一个。 为了让事情变得更好,该接口仅有的两个实现是包保护的,所以你需要使用一些魔法反射来实例化。 实现它的具体类是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
Answer 2:
罗曼提供了良好的答案以上 ,但它使用从行家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();
}
一个工作的例子是在层次,Maven的插件
Answer 3:
也许是你太晚了,但如果它可以帮助别人的未来。 所以,我做了这样的:
@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);
仅此而已。 它应该工作。 如果你有一些特殊的包装(如包...)在目标聚甲醛项目,确保有关的那些包装插件安装在你的当前项目。
Answer 4:
行家帮助插件确实当“MVN帮助:有效-POM”类似的东西被执行。
看到http://svn.apache.org/viewvc/maven/plugins/tags/maven-help-plugin-2.1.1/src/main/java/org/apache/maven/plugins/help/EffectivePomMojo.java?view =标记的来源。
我认为这将不显示传递depedencies。
该MVN依赖性:树目标,这是否: 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
也许你可以创建两者的混合?
Answer 5:
你追求的源代码是在help:effective-pom
,某处。
---编辑更新---
经过看一眼 ,这似乎是你需要建立一个Maven Project
从读取POM。 这可能会涉及到一定数量的包括POM的父项目的分辨率,下载和解析等Maven插件文物和接线所有引用的共同步骤。
独自阅读儿童级POM不会去做。
Answer 6:
万一有人想吧,这里是在Groovy运行的例子。 它使用葡萄动态加载以消耗的pom.xml所需的depdencies。 它加载这两个运行时类路径和测试类路径。
@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");
文章来源: How do I obtain a fully resolved Model of a pom file?