Mojo Parameter Expressions
Mojo parameter values are resolved by way of parameter expressions when a mojo is initialized. These expressions allow a mojo to traverse complex build state, and extract only the information it requires. This reduces the complexity of the code contained in the mojo, and often eliminates dependencies on Maven itself beyond the plugin API.
This section discusses the expression language used by Maven to inject build state and plugin configuration into mojos. It will summarize the root objects of the build state which are available for mojo expressions. Finally, it will describe the algorithm used to resolve complex parameter expressions.
Using the discussion below, along with the published Maven API documentation, mojo developers should have everything they need to extract the build state they require.
Simple Expressions
Maven’s plugin parameter injector supports several primitive expressions, which act as a shorthand for referencing commonly used build state objects. They are summarized below:
Table A-5: Primitive expressions supported by Maven’s plugin parameter
| Expression | Type | Description |
|---|---|---|
${localRepository} |
org.apache.maven.artifact |
This is a reference to the local repository used to cache artifacts during a Maven build. |
${session} |
org.apache.maven.execution |
The current build session. This contains methods for accessing information about how Maven was called, in addition to providing a mechanism for looking up Maven components on-demand. |
${reactorProjects} |
java.util.List<org.apache |
List of project instances which will be processed as part of the current build. |
| ${reports} | java.util.List<org.apache |
List of reports to be generated when the site life cycle executes. |
${executedProject} |
org.apache.maven.project |
This is a cloned instance of the project instance currently being built. It is used for bridging results from forked life cycles back to the main line of execution. |
Complex Expression Roots
In addition to the simple expressions above, Maven supports more complex expressions that traverse the object graph starting at some root object that contains build state. The valid root objects for plugin parameter expressions are summarized below:
Table A-6: A summary of the valid root objects for plugin parameter expressions
| Expression Root | Type | Description |
|---|---|---|
${basedir} |
java.io.File |
The current project’s root directory. |
${project} |
org.apache.maven |
Project instance which is currently being built. |
${settings} |
org.apache.maven |
The Maven settings, merged from conf/settings.xml in the maven application directory and from .m2/settings.xml in the user’s home directory, unless specified otherwise. |
${plugin} |
org.apache.maven.plugin |
The descriptor instance for the current plugin, including its dependency artifacts. |
The Expression Resolution Algorithm
Plugin parameter expressions are resolved using a straightforward algorithm. First, if the expression matches one of the primitive expressions (mentioned above) exactly, then the value mapped to that expression is returned. No advanced navigation can take place using is such expressions.
Otherwise, the expression is split at each ‘.’ character, rendering an array of navigational directions. The first is the root object, and must correspond to one of the roots mentioned above. This root object is retrieved from the running application using a hard-wired mapping, much like a primitive expression would. From there, the next expression part is used as a basis for reflectively traversing that object’ state. During this process, an expression part named ‘child’ translates into a call to the getChild() method on that object, following standard JavaBeans naming conventions. The resulting value then becomes the new ‘root’ object for the next round of traversal, if there is one. Repeating this, successive expression parts will extract values from deeper and deeper inside the build state.
When there are no more expression parts, the value that was resolved last will be returned as the expression’s value. If at some point the referenced object doesn’t contain a property that matches the next expression part, this reflective lookup process is aborted.
If at this point Maven still has not been able to resolve a value for the parameter expression, it will attempt to find a value in one of two remaining places, resolved in this order:
- The POM properties. If a user has specified a property mapping this expression to a specific value in the current POM, an ancestor POM, or an active profile, it will be resolved as the parameter value at this point.
- The system properties. If the value is still empty, Maven will consult the current system properties. This includes properties specified on the command line using the -D command-line option.
If the parameter is still empty after these two lookups, then the string literal of the expression itself is used as the resolved value. Currently, Maven plugin parameter expressions do not support collection lookups, array index references, or method invocations that don’t conform to standard JavaBean naming conventions.
Plugin metadata
Below is a review of the mechanisms used to specify metadata for plugins. It includes summaries of the essential plugin descriptor, as well as the metadata formats which are translated into plugin descriptors from Java- and Ant-specific mojo source files.
Plugin descriptor syntax
The following is a sample plugin descriptor. Its syntax has been annotated to provide descriptions of the elements.
<plugin>
<!-- The description element of the plugin's POM. -->
<description>Sample Maven Plugin</description>
<!-- These are the identity elements (groupId/artifactId/version)
| from the plugin POM.
|->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-myplugin-plugin</artifactId>
<version>2.0-SNAPSHOT</version>
<!-- This element provides the shorthand reference for this plugin. For
| instance, this plugin could be referred to from the command line using
| the 'myplugin:' prefix.
|->
<goalPrefix>myplugin</goalPrefix>
<!-- Whether the configuration for this mojo should be inherted from
| parent to child POMs by default.
|->
<inheritedByDefault>true</inheritedByDefault>
<!-- This is a list of the mojos contained within this plugin. -->
<mojos>
<mojo>
<!-- The name of the mojo. Combined with the 'goalPrefix' element above,
| this name allows the user to invoke this mojo from the command line
| using 'myplugin:do-something'.
|->
<goal>do-something</goal>
<!-- Description of what this mojo does. -->
<description>Do something cool.</description>
<!-- This tells Maven to create a clone of the current project and
| life cycle, then execute that life cycle up to the specified phase.
| This is useful when the user will be invoking this mojo directly from
| the command line, but the mojo itself has certain life-cycle
| prerequisites.
|->
<executePhase>process-resources</executePhase>
<!-- This is optionally used in conjunction with the executePhase element,
| and specifies a custom life-cycle overlay that should be added to the
| cloned life cycle before the specified phase is executed. This is
| useful to inject specialized behavior in cases where the main life
| cycle should remain unchanged.
|->
<executeLifecycle>myLifecycle</executeLifecycle>
<!-- Ensure that this other mojo within the same plugin executes before
| this one. It's restricted to this plugin to avoid creating inter-plugin
| dependencies.
|->
<executeGoal>do-something-first</executeGoal>
<!-- Which phase of the life cycle this mojo will bind to by default.
| This allows the user to specify that this mojo be executed (via the
| <execution> section of the plugin configuration in the POM), without
| also having to specify which phase is appropriate for the mojo's
| execution. It is a good idea to provide this, to give users a hint
| at where this task should run.
|->
<phase>compile</phase>
<!-- Tells Maven that this mojo can ONLY be invoked directly, via the
| command line.
|->
<requiresDirectInvocation>false</requiresDirectInvocation>
<!-- Tells Maven that a valid project instance must be present for this
| mojo to execute.
|->
<requiresProject>true</requiresProject>
<!-- Tells Maven that a valid list of reports for the current project are
| required before this plugin can execute.
|->
<requiresReports>false</requiresReports>
<!-- Determines how Maven will execute this mojo in the context of a
| multimodule build. If a mojo is marked as an aggregator, it will only
| execute once, regardless of the number of project instances in the
| current build. Mojos that are marked as aggregators should use the
| ${reactorProjects} expression to retrieve a list of the project
| instances in the current build. If the mojo is not marked as an
| aggregator, it will be executed once for each project instance in the
| current build.
|->
<aggregator>false</aggregator>
<!-- Some mojos cannot execute if they don't have access to a network
| connection. If Maven is operating in offline mode, such mojos will
| cause the build to fail. This flag controls whether the mojo requires
| Maven to be online.
|->
<requiresOnline>false</requiresOnline>
<!-- Tells Maven that the this plugin's configuration should be inherted
| from a parent POM by default, unless the user specifies
| <inherit>false</inherit>.
|->
<inheritedByDefault>true</inheritedByDefault>
<!-- The class or script path (within the plugin's jar) for this mojo's
| implementation.
|->
<implementation>org.apache.maven.plugins.site.SiteDeployMojo</implementation>
<!-- The implementation language for this mojo. -->
<language>java</language>
<!-- This is a list of the parameters used by this mojo. -->
<parameters>
<parameter>
<!-- The parameter's name. In Java mojos, this will often reflect the
| parameter field name in the mojo class.
|->
<name>inputDirectory</name>
<!-- This is an optional alternate parameter name for this parameter.
| It will be used as a backup for retrieving the parameter value.
|->
<alias>outputDirectory</alias>
<!-- The Java type for this parameter. -->
<type>java.io.File</type>
<!-- Whether this parameter is required to have a value. If true, the
| mojo (and the build) will fail when this parameter doesn't have a
| value.
|->
<required>true</required>
<!-- Whether this parameter's value can be directly specified by the
| user, either via command-line or POM configuration. If set to
| false, this parameter must be configured via some other section of
| the POM, as in the case of the list of project dependencies.
|->
<editable>true</editable>
<!-- Description for this parameter, specified in the javadoc comment
| for the parameter field in Java mojo implementations.
|->
<description>This parameter does something important.</description>
</parameter>
</parameters>
<!-- This is the operational specification of this mojo's parameters, as
| compared to the descriptive specification above. Each parameter must
| have an entry here that describes the parameter name, parameter type,
| and the primary expression used to extract the parameter's value.
|
| The general form is:
| <param-name implementation="param-type">param-expr</param-name>
|
|->
<configuration>
<!-- For example, this parameter is named "inputDirectory", and it
| expects a type of java.io.File. The expression used to extract the
| parameter value is ${project.reporting.outputDirectory}.
|->
<inputDirectory implementation="java.io.File">${project.reporting.outputDirectory}</inputDirectory>
</configuration>
<!-- This is the list of non-parameter component references used by this
| mojo. Components are specified by their interface class name (role),
| along with an optional classifier for the specific component instance
| to be used (role-hint). Finally, the requirement specification tells
| Maven which mojo-field should receive the component instance.
|->
<requirements>
<requirement>
<!-- Use a component of type:
org.apache.maven.artifact.manager.WagonManager
|->
<role>org.apache.maven.artifact.manager.WagonManager</role>
<!-- Inject the component instance into the "wagonManager" field of
| this mojo.
|->
<field-name>wagonManager</field-name>
</requirement>
</requirements>
</mojo>
</mojos>
</plugin>
Java Mojo Metadata: Supported Javadoc Annotations
The Javadoc annotations used to supply metadata about a particular mojo come in two types. Class-level annotations correspond to mojo-level metadata elements, and field-level annotations correspond to parameter-level metadata elements.
Class-level annotations
The table below summarizes the class-level javadoc annotations which translate into specific elements of the mojo section in the plugin descriptor.
Table A-7: A summary of class-level javadoc annotations
| Descriptor Element | Javadoc Annotation |
Values |
Required? |
|---|---|---|---|
| aggregator | @aggregator |
true or false (default is false) |
No |
| description | N/A (class comment) |
Anything |
No (recommended) |
| executePhase, executeLifecycle, executeGoal | @execute
goal=”mojo” phase=”phase” lifecycle=”lifecycle” |
Any valid mojo, phase, life cycle name. |
No |
| goal | @goal |
Alphanumeric, with dash (‘-’) |
Yes |
| phase | @phase |
Any valid phase name |
No |
| requiresDirectInvocation | @requiresDirectInvocation |
true or false (default is false) |
No |
| requiresProject | @requiresProject |
true or false (default is true) |
No |
| requiresReports | @requiresReports |
true or false (default is false) |
No |
| requiresOnline | @requiresOnline |
true or false (default is false) |
No |
Field-level annotations
The table below summarizes the field-level annotations which supply metadata about mojo parameters. These metadata translate into elements within the parameter, configuration, and requirements sections of a mojo’s specification in the plugin descriptor.
Table A-8: Field-level annotations
| Descriptor Element | Javadoc Annotation | Values | Required? |
|---|---|---|---|
| alias, parameter-configuration section | @parameter
expression=”${expr}” alias=”alias” default-value=”val” |
Anything |
Yes |
| Requirements section | @component
roleHint=”someHint” |
roleHint is optional, and usually left blank |
No |
| required | @required |
None |
No |
| editable | @readonly |
None |
No |
| description | N/A (field comment) |
Anything |
No (recommended) |
| deprecated | @deprecated |
Alternative parameter |
No |
Ant Metadata Syntax
The following is a sample Ant-based mojo metadata file. Its syntax has been annotated to provide descriptions of the elements.
<pluginMetadata>
<!-- Contains the list of mojos described by this metadata file. NOTE:
| multiple mojos are allowed here, corresponding to the ability to map
| multiple mojos into a single build script.
|->
<mojos>
<mojo>
<!-- The name for this mojo -->
<goal>myGoal</goal>
<!-- The default life-cycle phase binding for this mojo -->
<phase>compile</phase>
<!-- The dependency scope required for this mojo; Maven will resolve
| the dependencies in this scope before this mojo executes.
|->
<requiresDependencyResolution>compile</requiresDependencyResolution>
<!-- Whether this mojo requires a current project instance -->
<requiresProject>true</requiresProject>
<!-- Whether this mojo requires access to project reports -->
<requiresReports>true</requiresReports>
<!-- Whether this mojo requires Maven to execute in online mode -->
<requiresOnline>true</requiresOnline>
<!-- Whether the configuration for this mojo should be inherited
| from parent to child POMs by default.
|->
<inheritByDefault>true</inheritByDefault>
<!-- Whether this mojo must be invoked directly from the command
| line.
|->
<requiresDirectInvocation>true</requiresDirectInvocation>
<!-- Whether this mojo operates as an aggregator -->
<aggregator>true</aggregator>
<!-- This describes the mechanism for forking a new life cycle to be
| executed prior to this mojo executing.
|->
<execute>
<!-- The phase of the forked life cycle to execute -->
<phase>initialize</phase>
<!-- A named overlay to augment the cloned life cycle for this fork
| only
|->
<lifecycle>mine</lifecycle>
<!-- Another mojo within this plugin to execute before this mojo
| executes.
|->
<goal>goal</goal>
</execute>
<!-- List of non-parameter application components used in this mojo -->
<components>
<component>
<!-- This is the type for the component to be injected. -->
<role>org.apache.maven.artifact.resolver.ArtifactResolver</role>
<!-- This is an optional classifier for which instance of a particular
| component type should be used.
|->
<hint>custom</hint>
</component>
</components>
<!-- The list of parameters this mojo uses -->
<parameters>
<parameter>
<!-- The parameter name. -->
<name>nom</name>
<!-- The property name used by Ant tasks to reference this parameter
| value.
|->
<property>prop</property>
<!-- Whether this parameter is required for mojo execution -->
<required>true</required>
<!-- Whether the user can edit this parameter directly in the POM
| configuration or the command line
|->
<readonly>true</readonly>
<!-- The expression used to extract this parameter's value -->
<expression>${my.property}</expression>
<!-- The default value provided when the expression won't resolve -->
<defaultValue>${project.artifactId}</defaultValue>
<!-- The Java type of this mojo parameter -->
<type>org.apache.maven.project.MavenProject</type>
<!-- An alternative configuration name for this parameter -->
<alias>otherProp</alias>
<!-- The description of this parameter -->
<description>Test parameter</description>
<!-- When this is specified, this element will provide advice for an
| alternative parameter to use instead.
|->
<deprecated>Use something else</deprecated>
</parameter>
</parameters>
<!-- The description of what the mojo is meant to accomplish -->
<description>
This is a test.
</description>
<!-- If this is specified, it provides advice on which alternative mojo
| to use.
|->
<deprecated>Use another mojo</deprecated>
</mojo>
</mojos>
</pluginMetadata>