How do I obtain a fully resolved Model of a pom file?

前端 未结 6 495
时光取名叫无心
时光取名叫无心 2021-01-30 11:40

How do I obtain a fully resolved Model of a pom file?

This is basically a rephrasing of How can i programmaticaly build the effective model of a pom file?

I\'m b

6条回答
  •  不思量自难忘°
    2021-01-30 12:21

    I did it :-)

    help:effective-pom and dependency:tree really did not help at all.

    I had to look at how maven builds the Model for the MavenProject that gets injected in the mojo. help:effective-pom already receives the resolved Model, and dependency:tree only builds a DependencyGraph, but it doesn't load the whole model for a pom into memory.

    By using the code below I was able to get a Model object with all the information from the parent, with resolved ${property} expressions, and expanded transitive dependencies.

    Here's how:

    1) Get a ModelResolver

    You will need an instance of interface org.apache.maven.model.resolution.ModelResolver. Unfortunately, maven doesn't provide one easily via dependency injection (at least I couldn't find one), so we'll have to build one. To make things even better, the only two implementations of that interface are package protected, so you need to use some reflection magic to instantiate it. The concrete classes that implement it are DefaultModelResolver and ProjectModelResolver. I was able to build a DefaultModelResolver like this

    /**
     * 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) Build the Model

    When you have a modelResolver, you can build the Model from a pom file like this:

    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;
    }
    

    Doesn't look pretty, but it worked for me.. :P

提交回复
热议问题