How to call maven-resources-plugin programatically

2019-05-11 11:56发布

问题:

I am writing a custom Maven plugin and part of the plugin's job is to filter-copy some resources.

The code I've written looks like this:

CopyResourcesMojo rm = new CopyResourcesMojo();             
rm.setOutputDirectory(outputDir); //determined dynamically in a loop
rm.setOverwrite(true);
rm.setFilters(filters);  //determined dynamically in a loop
rm.setResources(this.resources);  //Actually is of type List<Resource>
rm.execute(); //NulPointerException because rm's project member is null.

This throws a NullPointerException because the CopyResourceMojo doesn't have access to my mojo's project, and the CopyResourceMojo doesn't have a setProject() method I could use.

I have looked into using mojo-executor-maven-plugin. The problem I have with it is that using this library to call a plugin involves writing code that mirrors what the XML config would be for that plugin. My plugin will receive a list of resources (just like the maven-resources-plugin could) so if I am going to use mojo-executor-maven-plugin, I think I would have to write code to evaluate the inclusions and exclusions. I was hoping to make use of the maven-resources-plugin for this, so that behaviour is 100% consistent with other plugins that take resource lists as parameters.

Is there any other way to call a plugin from code, or to inject a project into another mojo? Or some other way to accomplish this?

回答1:

I did eventually find a way to do this using MavenResourcesFiltering and MavenResourcesExecution. Document is here: http://maven.apache.org/shared/maven-filtering/usage.html

I was able to get this code to do what I wanted:

/* Class members */
@Parameter(defaultValue="${project}",required=true, readonly=true)
protected MavenProject project;

@Parameter( defaultValue = "${session}", required = true, readonly = true )
protected MavenSession session;

@Component( role=org.apache.maven.shared.filtering.MavenResourcesFiltering.class, hint="default")
protected MavenResourcesFiltering mavenResourcesFiltering;

@Parameter( property = "encoding", defaultValue = "${project.build.sourceEncoding}" )
protected String encoding;

@Parameter
protected List<Resource> resources;


...

//Inside my plugin's execute() method: 
List<String> nonFilteredFileExtensions = new ArrayList<String>();
//resources is a parameter to my plugin, dir and filters are calculated within the plugin
MavenResourcesExecution mre = new MavenResourcesExecution(resources, dir, this.project, this.encoding, filters, nonFilteredFileExtensions, session);
mavenResourcesFiltering.filterResources(mre);

And I define resources in my plugin's configuration the usual way:

<resources>
    <resource>
        <directory>G:/MyPluginProject/src/test/resources/project-to-test/resources</directory>
        <excludes>
            <exclude>*.DAT</exclude>
        </excludes>
        <filtering>true</filtering>
    </resource>
</resources>

What's odd is that for <directory>, absolute paths work fine but I can't seem to get it to work with an expression such as ${basedir}. I'm probably overlooking something obvious here...



回答2:

Besides the mojo-executor there is no direct way to call another plugin from plugin code.

However plugins can execute a parallel lifecycle which can call other plugins via its own XML configuration.

http://books.sonatype.com/mvnref-book/reference/writing-plugins-sect-plugins-lifecycle.html