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?
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...
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