You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by de...@apache.org on 2006/06/18 10:54:25 UTC
svn commit: r415110 -
/maven/site/trunk/src/site/xdoc/developers/mojo-api-specification.xml
Author: dennisl
Date: Sun Jun 18 01:54:24 2006
New Revision: 415110
URL: http://svn.apache.org/viewvc?rev=415110&view=rev
Log:
Set svn:eol-style correctly
Modified:
maven/site/trunk/src/site/xdoc/developers/mojo-api-specification.xml (contents, props changed)
Modified: maven/site/trunk/src/site/xdoc/developers/mojo-api-specification.xml
URL: http://svn.apache.org/viewvc/maven/site/trunk/src/site/xdoc/developers/mojo-api-specification.xml?rev=415110&r1=415109&r2=415110&view=diff
==============================================================================
--- maven/site/trunk/src/site/xdoc/developers/mojo-api-specification.xml (original)
+++ maven/site/trunk/src/site/xdoc/developers/mojo-api-specification.xml Sun Jun 18 01:54:24 2006
@@ -1,723 +1,723 @@
-<?xml version="1.0"?>
-<!--
-/*
- * Copyright 2001-2004 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<document>
- <properties>
- <title>Maven 2.0 - Mojo API Specification</title>
- <author email="jdcasey@apache.org">John Casey</author>
- </properties>
- <body>
- <section name="Introduction">
- <p>Starting with Maven 2.0, plugins can be written in Java or any of a
- number of scripting languages. Additionally, Maven tries to stay out of
- the way of the programmer with its new Mojo API. This opens up the
- opportunity for many Mojos to be reused outside of Maven, or bridged
- into Maven from external systems like Ant.</p>
- <p>NOTE: For now, we will limit the discussion to Java-based Mojos, since
- each scripting language will present these same basic requirements with
- various forms of implementation.</p>
- <p>Although the requirements on Mojos are minimal by design, there are
- still a very few requirements that Mojo developers must keep in mind. <!-- First, a Mojo must have a method named <code>execute</code> which
- declares no parameters, and has a void return type. If this method
- throws an exception, that exception must either be a derivative of
- <code>java.lang.RuntimeException</code>, or a derivative of
- <code>org.apache.maven.plugin.MojoExecutionException</code>. It goes
- without saying that in the latter case, the execute method must declare
- that it throws this exception. Additionally, Mojos must declare a field
- for each parameter they specify, and these parameter fields will be
- populated before execute() is called (Maven does support other
- mechanisms for parameter injection, but they are not considered part of
- the preferred practice, and are therefore a topic for an advanced Mojo
- developer's guide). Finally, all Mojos must be accompanied by metadata
- describing parameters, lifecycle bindings, etc. This descriptor will be
- covered in more detail below.</p>
- <p>While this will satisfy the requirements for execution as a Mojo
- inside Maven, it is recommended that Mojos implement
- --> Basically, these Mojo requirements are embodied by the
- <code>org.apache.maven.plugin.Mojo</code>
- interface, which the Mojo
- must implement (or else extend its abstract base class counterpart
- <code>org.apache.maven.plugin.AbstractMojo</code>
- ). This interface
- guarantees the correct execution contract for the Mojo: no parameters,
- void return type, and a throws clause that allows only
- <code>org.apache.maven.plugin.MojoExecutionException</code>
- and its
- derivatives. It also guarantees that the Mojo will have access to the
- standard Maven user-feedback mechanism,
- <code>org.apache.maven.monitor.logging.Log</code>
- , so the Mojo can
- communicate important events to the console or other log sink.<!-- Using the
- Plugin/Mojo API will give that Mojo access to the Maven-integrated Log,
- along with tighter integration into the Maven build. -->
- </p>
- <p>As mentioned before, each Plugin - or packaged set of Mojos - must
- provide a descriptor called
- <code>plugin.xml</code>
- under the path
- <code>META-INF/maven</code>
- inside the Plugin jar file. Fortunately,
- Maven also provides a set of Javadoc annotations and tools to generate
- this descriptor, so developers don't have to worry about directly
- authoring or maintaining a separate XML metadata file.
- </p>
- <p>To serve as a quick reference for the developer, the rest of this page
- will document these features (the API, along with the annotations)
- which are considered the best practice for developing Mojos.</p>
- </section>
- <section name="API Documentation">
- <subsection name="org.apache.maven.plugin.Mojo">
- <p>This interface forms the contract required for Mojos to interact
- with the Maven infrastructure. It features an
- <code>execute()</code>
- method, which triggers the Mojo's build-process behavior, and can
- throw a
- <code>MojoExecutionException</code>
- if an error condition
- occurs. See below for a discussion on proper use of this
- <code>Exception</code>
- class. Also included is the
- <code>setLog(..)</code>
- method, which simply allows Maven to inject a
- logging mechanism which will allow the Mojo to communicate to the
- outside world through standard Maven channels.
- </p>
- <p>
- <ul>
- <lt>
- <b>Method Summary:</b>
- </lt>
- <li>
- <code>
- void setLog( org.apache.maven.monitor.logging.Log )
- </code>
- <p>Inject a standard Maven logging mechanism to allow this Mojo
- to communicate events and feedback to the user.</p>
- </li>
- <li>
- <code>
- void execute() throws org.apache.maven.plugin.MojoExecutionException
- </code>
- <p>Perform whatever build-process behavior this Mojo implements.
- This is the main trigger for the Mojo inside the Maven system,
- and allows the Mojo to communicate fatal errors by throwing an
- instance of
- <code>MojoExecutionException</code>
- .
- </p>
- <p>The
- <code>MojoExecutionException</code>
- (and all error
- conditions inside the Mojo) should be handled very carefully.
- The simple wrapping of lower-level exceptions without providing
- any indication of a user-friendly probable cause is strictly
- discouraged. In fact, a much better course of action is to
- provide error handling code (try/catch stanzas) for each
- coherent step within the Mojo's execution. Developers are then
- in a much better position to diagnose the cause of any error,
- and provide user-friendly feedback in the message of the
- <code>MojoExecutionException</code>
- .
- </p>
- </li>
- </ul>
- </p>
- </subsection>
- <subsection name="org.apache.maven.plugin.AbstractMojo">
- <p>Currently, this abstract base class simply takes care of managing
- the Maven log for concrete derivations. In keeping with this, it
- provides a
- <code>protected</code>
- method,
- <code>getLog():Log</code>
- ,
- to furnish Log access to these concrete implementations.
- </p>
- <p>
- <ul>
- <lt>
- <b>Method Summary:</b>
- </lt>
- <li>
- <code>
- public void setLog( org.apache.maven.monitor.logging.Log )
- </code>
- <p>
- <b>[IMPLEMENTED]</b>
- </p>
- <p>Inject a standard Maven logging mechanism to allow this Mojo
- to communicate events and feedback to the user.</p>
- </li>
- <li>
- <code>protected Log getLog()</code>
- <p>
- <b>[IMPLEMENTED]</b>
- </p>
- <p>Furnish access to the standard Maven logging mechanism which
- is managed in this base class.</p>
- </li>
- <li>
- <code>
- void execute() throws org.apache.maven.plugin.MojoExecutionException
- </code>
- <p>
- <b>[ABSTRACT]</b>
- </p>
- <p>Perform whatever build-process behavior this Mojo implements.
- See the documentation for
- <code>Mojo</code>
- above for more
- information.
- </p>
- </li>
- </ul>
- </p>
- </subsection>
- <subsection name="org.apache.maven.monitor.logging.Log">
- <p>This interface supplies the API for providing feedback to the user
- from the Mojo, using standard Maven channels. There should be no big
- surprises here, although you may notice that the methods accept
- <code>java.lang.CharSequence</code>
- rather than
- <code>java.lang.String</code>
- . This is provided mainly as a
- convenience, to enable developers to pass things like
- <code>StringBuffer</code>
- directly into the logger, rather than
- formatting first by calling
- <code>toString()</code>
- .
- </p>
- <p>
- <ul>
- <lt>
- <b>Method Summary:</b>
- </lt>
- <li>
- <code>void debug( java.lang.CharSequence )</code>
- <p>Send a message to the user in the
- <b>debug</b>
- error level.
- </p>
- </li>
- <li>
- <code>
- void debug( java.lang.CharSequence, java.lang.Throwable )
- </code>
- <p>Send a message (and accompanying exception) to the user in the
- <b>debug</b>
- error level. The error's stacktrace will be output
- when this error level is enabled.
- </p>
- </li>
- <li>
- <code>void debug( java.lang.Throwable )</code>
- <p>Send an exception to the user in the
- <b>debug</b>
- error level.
- The stack trace for this exception will be output when this
- error level is enabled.
- </p>
- </li>
- <li>
- <code>void info( java.lang.CharSequence )</code>
- <p>Send a message to the user in the
- <b>info</b>
- error level.
- </p>
- </li>
- <li>
- <code>
- void info( java.lang.CharSequence, java.lang.Throwable )
- </code>
- <p>Send a message (and accompanying exception) to the user in the
- <b>info</b>
- error level. The error's stacktrace will be output
- when this error level is enabled.
- </p>
- </li>
- <li>
- <code>void info( java.lang.CharSequence )</code>
- <p>Send an exception to the user in the
- <b>info</b>
- error level.
- The stack trace for this exception will be output when this
- error level is enabled.
- </p>
- </li>
- <li>
- <code>void warn( java.lang.CharSequence )</code>
- <p>Send a message to the user in the
- <b>warn</b>
- error level.
- </p>
- </li>
- <li>
- <code>
- void warn( java.lang.CharSequence, java.lang.Throwable )
- </code>
- <p>Send a message (and accompanying exception) to the user in the
- <b>warn</b>
- error level. The error's stacktrace will be output
- when this error level is enabled.
- </p>
- </li>
- <li>
- <code>void warn( java.lang.CharSequence )</code>
- <p>Send an exception to the user in the
- <b>warn</b>
- error level.
- The stack trace for this exception will be output when this
- error level is enabled.
- </p>
- </li>
- <li>
- <code>void error( java.lang.CharSequence )</code>
- <p>Send a message to the user in the
- <b>error</b>
- error level.
- </p>
- </li>
- <li>
- <code>
- void error( java.lang.CharSequence, java.lang.Throwable )
- </code>
- <p>Send a message (and accompanying exception) to the user in the
- <b>error</b>
- error level. The error's stacktrace will be output
- when this error level is enabled.
- </p>
- </li>
- <li>
- <code>void error( java.lang.CharSequence )</code>
- <p>Send an exception to the user in the
- <b>error</b>
- error level.
- The stack trace for this exception will be output when this
- error level is enabled.
- </p>
- </li>
- </ul>
- </p>
- </subsection>
- </section>
- <section name="The Descriptor and Annotations">
- <p>In addition to the normal Java requirements in terms of interfaces
- and/or abstract base classes which need to be implemented, a plugin
- descriptor must accompany these classes inside the plugin jar. This
- descriptor file is used to provide metadata about the parameters and
- other component requirements for a set of Mojos so that Maven can
- initialize the Mojo and validate its configuration before executing
- it. As such, the plugin descriptor has a certain set of information
- that is required for each Mojo specification to be valid, as well as
- requirements for the overall plugin descriptor itself.</p>
- <p>NOTE: In the following discussion, bolded items are the descriptor's
- element name along with a Javadoc annotation (if applicable) supporting
- that piece of the plugin descriptor. A couple of examples are:
- <b>someElement
- (@annotation parameterName="parameterValue")</b>
- or
- <b>someOtherElement (@annotation <rawAnnotationValue>)</b>
- .
- </p>
- <p>The plugin descriptor must be provided in a jar resource with the
- path:
- <code>META-INF/maven/plugin.xml</code>
- , and it must contain the
- following:
- </p>
- <p>
- <table>
- <tr>
- <th>Descriptor Element</th>
- <th>Required?</th>
- <th>Notes</th>
- </tr>
- <tr>
- <td>mojos</td>
- <td>Yes</td>
- <td>Descriptors for each Mojo provided by the plugin, each inside a
- <b>mojo</b>
- sub-element. Mojo descriptors are covered in detail
- below. Obviously, a plugin without any declared Mojos doesn't
- make sense, so the
- <b>mojos</b>
- element is required, along with
- at least one
- <b>mojo</b>
- sub-element.
- </td>
- </tr>
- <tr>
- <td>dependencies</td>
- <td>Yes</td>
- <td>A set of dependencies which the plugin requires in order to
- function. Each dependency is provided inside a
- <b>dependency</b>
- sub-element. Dependency specifications are covered below. Since
- all plugins must have a dependency on
- <code>maven-plugin-api</code>
- , this element is effectively
- required.
- <i>Using the plugin toolset, these dependencies can be
- extracted from the POM's dependencies.</i>
- </td>
- </tr>
- </table>
- </p>
- <p>Each Mojo specified inside a plugin descriptor must provide the
- following (annotations specified here are at the class level):</p>
- <p>
- <table>
- <tr>
- <th>Descriptor Element</th>
- <th>Annotation</th>
- <th>Required?</th>
- <th>Notes</th>
- </tr>
- <tr>
- <td>goal</td>
- <td>@goal <goalName></td>
- <td>Yes</td>
- <td>The name for the Mojo that users will reference from the
- command line to execute the Mojo directly, or inside a POM in
- order to provide Mojo-specific configuration.</td>
- </tr>
- <tr>
- <td>implementation</td>
- <td>none (detected)</td>
- <td>Yes</td>
- <td>The Mojo's fully-qualified class name (or script path in
- the case of non-Java Mojos).</td>
- </tr>
- <tr>
- <td>language</td>
- <td>none (detected)</td>
- <td>No. Default:
- <code>java</code>
- </td>
- <td>The implementation language for this Mojo (Java,
- beanshell, etc.).</td>
- </tr>
- <tr>
- <td>configurator</td>
- <td>@configurator <roleHint></td>
- <td>No</td>
- <td>The configurator type to use when injecting parameter values
- into this Mojo. The value is normally deduced from the
- Mojo's implementation language, but can be specified to
- allow a custom ComponentConfigurator implementation to be used.
- <i>NOTE: This will only be used in very special
- cases, using a highly controlled vocabulary of possible values.
- (Elements like this are why it's a good idea to use the
- descriptor tools.)</i>
- </td>
- </tr>
- <tr>
- <td>phase</td>
- <td>@phase <phaseName></td>
- <td>No</td>
- <td>Binds this Mojo to a particular phase of the standard build
- lifecycle, if specified.
- <i>NOTE: This is only required if this
- Mojo is to participate in the standard build process.</i>
- </td>
- </tr>
- <tr>
- <td>execute</td>
- <td>@execute [phase=<phaseName>|goal=<goalName>] [lifecycle=<lifecycleId>]</td>
- <td>No</td>
- <td>When this goal is invoked, it will first invoke a parallel lifecycle, ending at the given phase.
- If a goal is provided instead of a phase, that goal will be executed in isolation. The execution of either
- will not affect the current project, but instead make available the
- <code>${executedProject}</code>
- expression if required. An alternate lifecycle can also be provided: for more information see the
- documentation on the
- <a href="../guides/introduction/introduction-to-the-lifecycle.html">build lifecycle</a>
- .
- </td>
- </tr>
- <tr>
- <td>requiresDependencyResolution</td>
- <td>@requiresDependencyResolution <requiredScope></td>
- <td>No</td>
- <td>Flags this Mojo as requiring the dependencies in the specified
- scope (or an implied scope) to be resolved before it can execute.
- <i>NOTE: Currently supports
- <b>compile</b>
- ,
- <b>runtime</b>
- , and
- <b>test</b>
- scopes.
- </i>
- </td>
- </tr>
- <tr>
- <td>description</td>
- <td>none (detected)</td>
- <td>No</td>
- <td>The description of this Mojo's functionality.
- <i>Using the
- toolset, this will be the class-level Javadoc description
- provided. NOTE: While this is not a required part of the Mojo
- specification, it SHOULD be provided to enable future
- tool support for browsing, etc. and for clarity.</i>
- </td>
- </tr>
- <tr>
- <td>parameters</td>
- <td>N/A</td>
- <td>No</td>
- <td>Specifications for the parameters which this Mojo uses will be
- provided in
- <b>parameter</b>
- sub-elements in this section.
- <i>NOTE: Parameters are discussed in more detail below.</i>
- </td>
- </tr>
- </table>
- </p>
- <p>Each Mojo specifies the parameters that it expects in order to work.
- These parameters are the Mojo's link to the outside world, and
- will be satisfied through a combination of POM/project values, plugin
- configurations (from the POM and configuration defaults), and System
- properties.</p>
- <p>NOTE[1]: For this discussion on Mojo parameters, a single
- annotation may span multiple elements in the descriptor's specification
- for that parameter. Duplicate annotation declarations in this section
- will be used to detail each parameter of an annotation separately.</p>
- <p>NOTE[2]: In many cases, simply annotating a Mojo field with
- <b>@parameter</b>
- will be enough to allow injection of a value for that
- parameter using POM configuration elements. The discussion below
- shows advanced usage for this annotation, along with others.
- </p>
- <p>Each parameter for a Mojo must be specified in the
- plugin descriptor as follows:</p>
- <p>
- <table>
- <tr>
- <th>Descriptor Element</th>
- <th>Annotation</th>
- <th>Required?</th>
- <th>Notes</th>
- </tr>
- <tr>
- <td>name</td>
- <td>none (detected)</td>
- <td>Yes</td>
- <td>The name of the parameter, to be used in configuring this
- parameter from the Mojo's declared defaults (discussed below) or
- from the POM.
- <i>Using the toolset, this is detected as the
- Java field name.</i>
- </td>
- </tr>
- <tr>
- <td>alias</td>
- <td>@parameter alias="myAlias"</td>
- <td>No</td>
- <td>Specifies an alias which can be used to configure this
- parameter from the POM. This is primarily useful to improve
- user-friendliness, where Mojo field names are not intuitive to
- the user or are otherwise not conducive to configuration via
- the POM.</td>
- </tr>
- <tr>
- <td>type</td>
- <td>none (detected)</td>
- <td>Yes</td>
- <td>The Java type for this parameter. This is used to validate the
- result of any expressions used to calculate the value which
- should be injected into the Mojo for this parameter.
- <i>Using the
- toolset, this is detected as the class of the Java field
- corresponding to this parameter.</i>
- </td>
- </tr>
- <tr>
- <td>required</td>
- <td>@required</td>
- <td>No</td>
- <td>Whether this parameter is required for the Mojo to function.
- This is used to validate the configuration for a Mojo before it
- is injected, and before the Mojo is executed from some
- half-state.
- <i>NOTE: Specification of this annotation flags
- the parameter as required; there is no true/false value.</i>
- </td>
- </tr>
- <tr>
- <td>editable</td>
- <td>@readonly</td>
- <td>No</td>
- <td>Specifies that this parameter cannot be configured directly by
- the user (as in the case of POM-specified configuration). This is
- useful when you want to force the user to use common POM elements
- rather than plugin configurations, as in the case where you want
- to use the artifact's final name as a parameter. In this case,
- you want the user to modify
- <build><finalName/></build> rather than
- specifying a value for finalName directly in the plugin
- configuration section. It is also useful to ensure that - for
- example - a List-typed parameter which expects items of type
- Artifact doesn't get a List full of Strings.
- <i>NOTE:
- Specification of this annotation flags the parameter as
- non-editable; there is no true/false value.</i>
- </td>
- </tr>
- <tr>
- <td>description</td>
- <td>none (detected)</td>
- <td>No</td>
- <td>The description of this parameter's use inside the Mojo.
- <i>Using the toolset, this is detected as the Javadoc description
- for the field. NOTE: While this is not a required part of the
- parameter specification, it SHOULD be provided to enable future
- tool support for browsing, etc. and for clarity.</i>
- </td>
- </tr>
- <tr>
- <td>configuration</td>
- <td>@parameter expression="${someExpression}" default-value="value"</td>
- <td>No</td>
- <td>Specifies the expression used to calculate the value to be
- injected into this parameter of the Mojo at buildtime. This is
- commonly used to refer to specific elements in the POM, such as
- ${project.build.resources}, which refers to the List of resources
- meant to accompany the classes in the resulting jar file.
- The default value is used when the expression evaluates to
- <code>null</code>
- .
- <i>NOTE: If not specified, an expression of ${<name>} is
- assumed, which can only be satisfied from POM configuration or
- System properties. The use of '${' and '}' is required to delimit
- actual expressions which may be evaluated.</i>
- </td>
- </tr>
- <tr>
- <td>deprecated</td>
- <td>@deprecated</td>
- <td>No</td>
- <td>Marks a parameter as deprecated. The rules on deprecation are
- the same as normal Java with language elements. This will trigger
- a warning when a user tries to configure a parameter marked as
- deprecated.</td>
- </tr>
- </table>
- </p>
- <p>The final component of a plugin descriptor is the dependencies. This
- enables the plugin to function independently of its POM (or at least
- to declare the libraries it needs to run). Dependencies are taken from
- the
- <b>runtime</b>
- scope of the plugin's calculated dependencies (from
- the POM). Dependencies are specified in exactly the same manner as in
- the POM, except for the <scope> element (all dependencies in the
- plugin descriptor are assumed to be runtime, because this is a
- runtime profile for the plugin).
- </p>
- </section>
- <section name="Plugin Tools">
- <p>By now, we've mentioned the plugin tools several times without telling
- you what they are or how to use them. Instead of manually writing (and
- maintaining) the metadata detailed above, Maven 2.0 ships with some
- tools to aid in this task. In fact, the only thing a plugin developer
- needs to do is declare his project to be a plugin from within the POM.
- Once this is done, Maven will call the appropriate descriptor
- generators, etc. to produce an artifact that is ready for use within
- Maven builds. Optional metadata can be injected via Javadoc annotation
- (and possibly JDK5 annotations in the future) as described above,
- enabling richer interactions between the Mojo and the user. The
- section below describes the changes to the POM which are necessary to
- create plugin artifacts.</p>
- </section>
- <section name="Project Descriptor (POM) Requirements">
- <p>From the POM, Maven plugin projects look quite similar to any other
- project. For pure Java plugins, the differences are even smaller than
- for script-based plugins. The following details the POM elements
- which are necessary to build a Maven plugin artifact.</p>
- <p>
- <table>
- <tr>
- <th>POM Element</th>
- <th>Required for Java Mojos?</th>
- <th>Sample Declaration</th>
- <th>Notes</th>
- </tr>
- <tr>
- <td>packaging</td>
- <td>Yes</td>
- <td>
- <code><packaging>maven-plugin</packaging></code>
- </td>
- <td>The POM must declare a packaging element which describes this
- project as a Maven plugin project.</td>
- </tr>
- <tr>
- <td>scriptSourceDirectory</td>
- <td>No</td>
- <td>
- <code><scriptSourceDirectory>src/main/scripts</scriptSourceDirectory></code>
- </td>
- <td>In the case of script-based Mojos (which are not covered in
- detail within this document), the POM must include an additional
- element to distinguish script sources from (optional) Java
- supporting classes. This element is <code>scriptSourceDirectory</code>,
- inside the <code>build</code> section. This directory is included in the list
- of resources which accompany any compiled code in the resulting
- artifact. It is specified separately from the resources in the
- build section to denote its special status as an alternate source
- directory for scripts.</td>
- </tr>
- </table>
- </p>
- <p>After making the changes above, the developer can simply call
- <br/>
- <br/>
- <code>mvn install</code>
- <br/>
- <br/>
- to install the plugin to
- the local repository. (Any of the other standard lifecycle targets like
- package, deploy, etc. are also available in like fashion.)
- </p>
- </section>
- <section name="Resources">
- <p>This section simply gives a listing of pointers for more
- information.</p>
- <p>
- <ul>
- <li>M2 Plugin Overview [
- <a
- href="plugin-overview.html">link</a>
- ]
- </li>
- <li>QDox Project (Javadoc annotations) [
- <a
- href="http://qdox.codehaus.org">link</a>
- ]
- </li>
- </ul>
- </p>
- </section>
- </body>
-</document>
+<?xml version="1.0"?>
+<!--
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<document>
+ <properties>
+ <title>Maven 2.0 - Mojo API Specification</title>
+ <author email="jdcasey@apache.org">John Casey</author>
+ </properties>
+ <body>
+ <section name="Introduction">
+ <p>Starting with Maven 2.0, plugins can be written in Java or any of a
+ number of scripting languages. Additionally, Maven tries to stay out of
+ the way of the programmer with its new Mojo API. This opens up the
+ opportunity for many Mojos to be reused outside of Maven, or bridged
+ into Maven from external systems like Ant.</p>
+ <p>NOTE: For now, we will limit the discussion to Java-based Mojos, since
+ each scripting language will present these same basic requirements with
+ various forms of implementation.</p>
+ <p>Although the requirements on Mojos are minimal by design, there are
+ still a very few requirements that Mojo developers must keep in mind. <!-- First, a Mojo must have a method named <code>execute</code> which
+ declares no parameters, and has a void return type. If this method
+ throws an exception, that exception must either be a derivative of
+ <code>java.lang.RuntimeException</code>, or a derivative of
+ <code>org.apache.maven.plugin.MojoExecutionException</code>. It goes
+ without saying that in the latter case, the execute method must declare
+ that it throws this exception. Additionally, Mojos must declare a field
+ for each parameter they specify, and these parameter fields will be
+ populated before execute() is called (Maven does support other
+ mechanisms for parameter injection, but they are not considered part of
+ the preferred practice, and are therefore a topic for an advanced Mojo
+ developer's guide). Finally, all Mojos must be accompanied by metadata
+ describing parameters, lifecycle bindings, etc. This descriptor will be
+ covered in more detail below.</p>
+ <p>While this will satisfy the requirements for execution as a Mojo
+ inside Maven, it is recommended that Mojos implement
+ --> Basically, these Mojo requirements are embodied by the
+ <code>org.apache.maven.plugin.Mojo</code>
+ interface, which the Mojo
+ must implement (or else extend its abstract base class counterpart
+ <code>org.apache.maven.plugin.AbstractMojo</code>
+ ). This interface
+ guarantees the correct execution contract for the Mojo: no parameters,
+ void return type, and a throws clause that allows only
+ <code>org.apache.maven.plugin.MojoExecutionException</code>
+ and its
+ derivatives. It also guarantees that the Mojo will have access to the
+ standard Maven user-feedback mechanism,
+ <code>org.apache.maven.monitor.logging.Log</code>
+ , so the Mojo can
+ communicate important events to the console or other log sink.<!-- Using the
+ Plugin/Mojo API will give that Mojo access to the Maven-integrated Log,
+ along with tighter integration into the Maven build. -->
+ </p>
+ <p>As mentioned before, each Plugin - or packaged set of Mojos - must
+ provide a descriptor called
+ <code>plugin.xml</code>
+ under the path
+ <code>META-INF/maven</code>
+ inside the Plugin jar file. Fortunately,
+ Maven also provides a set of Javadoc annotations and tools to generate
+ this descriptor, so developers don't have to worry about directly
+ authoring or maintaining a separate XML metadata file.
+ </p>
+ <p>To serve as a quick reference for the developer, the rest of this page
+ will document these features (the API, along with the annotations)
+ which are considered the best practice for developing Mojos.</p>
+ </section>
+ <section name="API Documentation">
+ <subsection name="org.apache.maven.plugin.Mojo">
+ <p>This interface forms the contract required for Mojos to interact
+ with the Maven infrastructure. It features an
+ <code>execute()</code>
+ method, which triggers the Mojo's build-process behavior, and can
+ throw a
+ <code>MojoExecutionException</code>
+ if an error condition
+ occurs. See below for a discussion on proper use of this
+ <code>Exception</code>
+ class. Also included is the
+ <code>setLog(..)</code>
+ method, which simply allows Maven to inject a
+ logging mechanism which will allow the Mojo to communicate to the
+ outside world through standard Maven channels.
+ </p>
+ <p>
+ <ul>
+ <lt>
+ <b>Method Summary:</b>
+ </lt>
+ <li>
+ <code>
+ void setLog( org.apache.maven.monitor.logging.Log )
+ </code>
+ <p>Inject a standard Maven logging mechanism to allow this Mojo
+ to communicate events and feedback to the user.</p>
+ </li>
+ <li>
+ <code>
+ void execute() throws org.apache.maven.plugin.MojoExecutionException
+ </code>
+ <p>Perform whatever build-process behavior this Mojo implements.
+ This is the main trigger for the Mojo inside the Maven system,
+ and allows the Mojo to communicate fatal errors by throwing an
+ instance of
+ <code>MojoExecutionException</code>
+ .
+ </p>
+ <p>The
+ <code>MojoExecutionException</code>
+ (and all error
+ conditions inside the Mojo) should be handled very carefully.
+ The simple wrapping of lower-level exceptions without providing
+ any indication of a user-friendly probable cause is strictly
+ discouraged. In fact, a much better course of action is to
+ provide error handling code (try/catch stanzas) for each
+ coherent step within the Mojo's execution. Developers are then
+ in a much better position to diagnose the cause of any error,
+ and provide user-friendly feedback in the message of the
+ <code>MojoExecutionException</code>
+ .
+ </p>
+ </li>
+ </ul>
+ </p>
+ </subsection>
+ <subsection name="org.apache.maven.plugin.AbstractMojo">
+ <p>Currently, this abstract base class simply takes care of managing
+ the Maven log for concrete derivations. In keeping with this, it
+ provides a
+ <code>protected</code>
+ method,
+ <code>getLog():Log</code>
+ ,
+ to furnish Log access to these concrete implementations.
+ </p>
+ <p>
+ <ul>
+ <lt>
+ <b>Method Summary:</b>
+ </lt>
+ <li>
+ <code>
+ public void setLog( org.apache.maven.monitor.logging.Log )
+ </code>
+ <p>
+ <b>[IMPLEMENTED]</b>
+ </p>
+ <p>Inject a standard Maven logging mechanism to allow this Mojo
+ to communicate events and feedback to the user.</p>
+ </li>
+ <li>
+ <code>protected Log getLog()</code>
+ <p>
+ <b>[IMPLEMENTED]</b>
+ </p>
+ <p>Furnish access to the standard Maven logging mechanism which
+ is managed in this base class.</p>
+ </li>
+ <li>
+ <code>
+ void execute() throws org.apache.maven.plugin.MojoExecutionException
+ </code>
+ <p>
+ <b>[ABSTRACT]</b>
+ </p>
+ <p>Perform whatever build-process behavior this Mojo implements.
+ See the documentation for
+ <code>Mojo</code>
+ above for more
+ information.
+ </p>
+ </li>
+ </ul>
+ </p>
+ </subsection>
+ <subsection name="org.apache.maven.monitor.logging.Log">
+ <p>This interface supplies the API for providing feedback to the user
+ from the Mojo, using standard Maven channels. There should be no big
+ surprises here, although you may notice that the methods accept
+ <code>java.lang.CharSequence</code>
+ rather than
+ <code>java.lang.String</code>
+ . This is provided mainly as a
+ convenience, to enable developers to pass things like
+ <code>StringBuffer</code>
+ directly into the logger, rather than
+ formatting first by calling
+ <code>toString()</code>
+ .
+ </p>
+ <p>
+ <ul>
+ <lt>
+ <b>Method Summary:</b>
+ </lt>
+ <li>
+ <code>void debug( java.lang.CharSequence )</code>
+ <p>Send a message to the user in the
+ <b>debug</b>
+ error level.
+ </p>
+ </li>
+ <li>
+ <code>
+ void debug( java.lang.CharSequence, java.lang.Throwable )
+ </code>
+ <p>Send a message (and accompanying exception) to the user in the
+ <b>debug</b>
+ error level. The error's stacktrace will be output
+ when this error level is enabled.
+ </p>
+ </li>
+ <li>
+ <code>void debug( java.lang.Throwable )</code>
+ <p>Send an exception to the user in the
+ <b>debug</b>
+ error level.
+ The stack trace for this exception will be output when this
+ error level is enabled.
+ </p>
+ </li>
+ <li>
+ <code>void info( java.lang.CharSequence )</code>
+ <p>Send a message to the user in the
+ <b>info</b>
+ error level.
+ </p>
+ </li>
+ <li>
+ <code>
+ void info( java.lang.CharSequence, java.lang.Throwable )
+ </code>
+ <p>Send a message (and accompanying exception) to the user in the
+ <b>info</b>
+ error level. The error's stacktrace will be output
+ when this error level is enabled.
+ </p>
+ </li>
+ <li>
+ <code>void info( java.lang.CharSequence )</code>
+ <p>Send an exception to the user in the
+ <b>info</b>
+ error level.
+ The stack trace for this exception will be output when this
+ error level is enabled.
+ </p>
+ </li>
+ <li>
+ <code>void warn( java.lang.CharSequence )</code>
+ <p>Send a message to the user in the
+ <b>warn</b>
+ error level.
+ </p>
+ </li>
+ <li>
+ <code>
+ void warn( java.lang.CharSequence, java.lang.Throwable )
+ </code>
+ <p>Send a message (and accompanying exception) to the user in the
+ <b>warn</b>
+ error level. The error's stacktrace will be output
+ when this error level is enabled.
+ </p>
+ </li>
+ <li>
+ <code>void warn( java.lang.CharSequence )</code>
+ <p>Send an exception to the user in the
+ <b>warn</b>
+ error level.
+ The stack trace for this exception will be output when this
+ error level is enabled.
+ </p>
+ </li>
+ <li>
+ <code>void error( java.lang.CharSequence )</code>
+ <p>Send a message to the user in the
+ <b>error</b>
+ error level.
+ </p>
+ </li>
+ <li>
+ <code>
+ void error( java.lang.CharSequence, java.lang.Throwable )
+ </code>
+ <p>Send a message (and accompanying exception) to the user in the
+ <b>error</b>
+ error level. The error's stacktrace will be output
+ when this error level is enabled.
+ </p>
+ </li>
+ <li>
+ <code>void error( java.lang.CharSequence )</code>
+ <p>Send an exception to the user in the
+ <b>error</b>
+ error level.
+ The stack trace for this exception will be output when this
+ error level is enabled.
+ </p>
+ </li>
+ </ul>
+ </p>
+ </subsection>
+ </section>
+ <section name="The Descriptor and Annotations">
+ <p>In addition to the normal Java requirements in terms of interfaces
+ and/or abstract base classes which need to be implemented, a plugin
+ descriptor must accompany these classes inside the plugin jar. This
+ descriptor file is used to provide metadata about the parameters and
+ other component requirements for a set of Mojos so that Maven can
+ initialize the Mojo and validate its configuration before executing
+ it. As such, the plugin descriptor has a certain set of information
+ that is required for each Mojo specification to be valid, as well as
+ requirements for the overall plugin descriptor itself.</p>
+ <p>NOTE: In the following discussion, bolded items are the descriptor's
+ element name along with a Javadoc annotation (if applicable) supporting
+ that piece of the plugin descriptor. A couple of examples are:
+ <b>someElement
+ (@annotation parameterName="parameterValue")</b>
+ or
+ <b>someOtherElement (@annotation <rawAnnotationValue>)</b>
+ .
+ </p>
+ <p>The plugin descriptor must be provided in a jar resource with the
+ path:
+ <code>META-INF/maven/plugin.xml</code>
+ , and it must contain the
+ following:
+ </p>
+ <p>
+ <table>
+ <tr>
+ <th>Descriptor Element</th>
+ <th>Required?</th>
+ <th>Notes</th>
+ </tr>
+ <tr>
+ <td>mojos</td>
+ <td>Yes</td>
+ <td>Descriptors for each Mojo provided by the plugin, each inside a
+ <b>mojo</b>
+ sub-element. Mojo descriptors are covered in detail
+ below. Obviously, a plugin without any declared Mojos doesn't
+ make sense, so the
+ <b>mojos</b>
+ element is required, along with
+ at least one
+ <b>mojo</b>
+ sub-element.
+ </td>
+ </tr>
+ <tr>
+ <td>dependencies</td>
+ <td>Yes</td>
+ <td>A set of dependencies which the plugin requires in order to
+ function. Each dependency is provided inside a
+ <b>dependency</b>
+ sub-element. Dependency specifications are covered below. Since
+ all plugins must have a dependency on
+ <code>maven-plugin-api</code>
+ , this element is effectively
+ required.
+ <i>Using the plugin toolset, these dependencies can be
+ extracted from the POM's dependencies.</i>
+ </td>
+ </tr>
+ </table>
+ </p>
+ <p>Each Mojo specified inside a plugin descriptor must provide the
+ following (annotations specified here are at the class level):</p>
+ <p>
+ <table>
+ <tr>
+ <th>Descriptor Element</th>
+ <th>Annotation</th>
+ <th>Required?</th>
+ <th>Notes</th>
+ </tr>
+ <tr>
+ <td>goal</td>
+ <td>@goal <goalName></td>
+ <td>Yes</td>
+ <td>The name for the Mojo that users will reference from the
+ command line to execute the Mojo directly, or inside a POM in
+ order to provide Mojo-specific configuration.</td>
+ </tr>
+ <tr>
+ <td>implementation</td>
+ <td>none (detected)</td>
+ <td>Yes</td>
+ <td>The Mojo's fully-qualified class name (or script path in
+ the case of non-Java Mojos).</td>
+ </tr>
+ <tr>
+ <td>language</td>
+ <td>none (detected)</td>
+ <td>No. Default:
+ <code>java</code>
+ </td>
+ <td>The implementation language for this Mojo (Java,
+ beanshell, etc.).</td>
+ </tr>
+ <tr>
+ <td>configurator</td>
+ <td>@configurator <roleHint></td>
+ <td>No</td>
+ <td>The configurator type to use when injecting parameter values
+ into this Mojo. The value is normally deduced from the
+ Mojo's implementation language, but can be specified to
+ allow a custom ComponentConfigurator implementation to be used.
+ <i>NOTE: This will only be used in very special
+ cases, using a highly controlled vocabulary of possible values.
+ (Elements like this are why it's a good idea to use the
+ descriptor tools.)</i>
+ </td>
+ </tr>
+ <tr>
+ <td>phase</td>
+ <td>@phase <phaseName></td>
+ <td>No</td>
+ <td>Binds this Mojo to a particular phase of the standard build
+ lifecycle, if specified.
+ <i>NOTE: This is only required if this
+ Mojo is to participate in the standard build process.</i>
+ </td>
+ </tr>
+ <tr>
+ <td>execute</td>
+ <td>@execute [phase=<phaseName>|goal=<goalName>] [lifecycle=<lifecycleId>]</td>
+ <td>No</td>
+ <td>When this goal is invoked, it will first invoke a parallel lifecycle, ending at the given phase.
+ If a goal is provided instead of a phase, that goal will be executed in isolation. The execution of either
+ will not affect the current project, but instead make available the
+ <code>${executedProject}</code>
+ expression if required. An alternate lifecycle can also be provided: for more information see the
+ documentation on the
+ <a href="../guides/introduction/introduction-to-the-lifecycle.html">build lifecycle</a>
+ .
+ </td>
+ </tr>
+ <tr>
+ <td>requiresDependencyResolution</td>
+ <td>@requiresDependencyResolution <requiredScope></td>
+ <td>No</td>
+ <td>Flags this Mojo as requiring the dependencies in the specified
+ scope (or an implied scope) to be resolved before it can execute.
+ <i>NOTE: Currently supports
+ <b>compile</b>
+ ,
+ <b>runtime</b>
+ , and
+ <b>test</b>
+ scopes.
+ </i>
+ </td>
+ </tr>
+ <tr>
+ <td>description</td>
+ <td>none (detected)</td>
+ <td>No</td>
+ <td>The description of this Mojo's functionality.
+ <i>Using the
+ toolset, this will be the class-level Javadoc description
+ provided. NOTE: While this is not a required part of the Mojo
+ specification, it SHOULD be provided to enable future
+ tool support for browsing, etc. and for clarity.</i>
+ </td>
+ </tr>
+ <tr>
+ <td>parameters</td>
+ <td>N/A</td>
+ <td>No</td>
+ <td>Specifications for the parameters which this Mojo uses will be
+ provided in
+ <b>parameter</b>
+ sub-elements in this section.
+ <i>NOTE: Parameters are discussed in more detail below.</i>
+ </td>
+ </tr>
+ </table>
+ </p>
+ <p>Each Mojo specifies the parameters that it expects in order to work.
+ These parameters are the Mojo's link to the outside world, and
+ will be satisfied through a combination of POM/project values, plugin
+ configurations (from the POM and configuration defaults), and System
+ properties.</p>
+ <p>NOTE[1]: For this discussion on Mojo parameters, a single
+ annotation may span multiple elements in the descriptor's specification
+ for that parameter. Duplicate annotation declarations in this section
+ will be used to detail each parameter of an annotation separately.</p>
+ <p>NOTE[2]: In many cases, simply annotating a Mojo field with
+ <b>@parameter</b>
+ will be enough to allow injection of a value for that
+ parameter using POM configuration elements. The discussion below
+ shows advanced usage for this annotation, along with others.
+ </p>
+ <p>Each parameter for a Mojo must be specified in the
+ plugin descriptor as follows:</p>
+ <p>
+ <table>
+ <tr>
+ <th>Descriptor Element</th>
+ <th>Annotation</th>
+ <th>Required?</th>
+ <th>Notes</th>
+ </tr>
+ <tr>
+ <td>name</td>
+ <td>none (detected)</td>
+ <td>Yes</td>
+ <td>The name of the parameter, to be used in configuring this
+ parameter from the Mojo's declared defaults (discussed below) or
+ from the POM.
+ <i>Using the toolset, this is detected as the
+ Java field name.</i>
+ </td>
+ </tr>
+ <tr>
+ <td>alias</td>
+ <td>@parameter alias="myAlias"</td>
+ <td>No</td>
+ <td>Specifies an alias which can be used to configure this
+ parameter from the POM. This is primarily useful to improve
+ user-friendliness, where Mojo field names are not intuitive to
+ the user or are otherwise not conducive to configuration via
+ the POM.</td>
+ </tr>
+ <tr>
+ <td>type</td>
+ <td>none (detected)</td>
+ <td>Yes</td>
+ <td>The Java type for this parameter. This is used to validate the
+ result of any expressions used to calculate the value which
+ should be injected into the Mojo for this parameter.
+ <i>Using the
+ toolset, this is detected as the class of the Java field
+ corresponding to this parameter.</i>
+ </td>
+ </tr>
+ <tr>
+ <td>required</td>
+ <td>@required</td>
+ <td>No</td>
+ <td>Whether this parameter is required for the Mojo to function.
+ This is used to validate the configuration for a Mojo before it
+ is injected, and before the Mojo is executed from some
+ half-state.
+ <i>NOTE: Specification of this annotation flags
+ the parameter as required; there is no true/false value.</i>
+ </td>
+ </tr>
+ <tr>
+ <td>editable</td>
+ <td>@readonly</td>
+ <td>No</td>
+ <td>Specifies that this parameter cannot be configured directly by
+ the user (as in the case of POM-specified configuration). This is
+ useful when you want to force the user to use common POM elements
+ rather than plugin configurations, as in the case where you want
+ to use the artifact's final name as a parameter. In this case,
+ you want the user to modify
+ <build><finalName/></build> rather than
+ specifying a value for finalName directly in the plugin
+ configuration section. It is also useful to ensure that - for
+ example - a List-typed parameter which expects items of type
+ Artifact doesn't get a List full of Strings.
+ <i>NOTE:
+ Specification of this annotation flags the parameter as
+ non-editable; there is no true/false value.</i>
+ </td>
+ </tr>
+ <tr>
+ <td>description</td>
+ <td>none (detected)</td>
+ <td>No</td>
+ <td>The description of this parameter's use inside the Mojo.
+ <i>Using the toolset, this is detected as the Javadoc description
+ for the field. NOTE: While this is not a required part of the
+ parameter specification, it SHOULD be provided to enable future
+ tool support for browsing, etc. and for clarity.</i>
+ </td>
+ </tr>
+ <tr>
+ <td>configuration</td>
+ <td>@parameter expression="${someExpression}" default-value="value"</td>
+ <td>No</td>
+ <td>Specifies the expression used to calculate the value to be
+ injected into this parameter of the Mojo at buildtime. This is
+ commonly used to refer to specific elements in the POM, such as
+ ${project.build.resources}, which refers to the List of resources
+ meant to accompany the classes in the resulting jar file.
+ The default value is used when the expression evaluates to
+ <code>null</code>
+ .
+ <i>NOTE: If not specified, an expression of ${<name>} is
+ assumed, which can only be satisfied from POM configuration or
+ System properties. The use of '${' and '}' is required to delimit
+ actual expressions which may be evaluated.</i>
+ </td>
+ </tr>
+ <tr>
+ <td>deprecated</td>
+ <td>@deprecated</td>
+ <td>No</td>
+ <td>Marks a parameter as deprecated. The rules on deprecation are
+ the same as normal Java with language elements. This will trigger
+ a warning when a user tries to configure a parameter marked as
+ deprecated.</td>
+ </tr>
+ </table>
+ </p>
+ <p>The final component of a plugin descriptor is the dependencies. This
+ enables the plugin to function independently of its POM (or at least
+ to declare the libraries it needs to run). Dependencies are taken from
+ the
+ <b>runtime</b>
+ scope of the plugin's calculated dependencies (from
+ the POM). Dependencies are specified in exactly the same manner as in
+ the POM, except for the <scope> element (all dependencies in the
+ plugin descriptor are assumed to be runtime, because this is a
+ runtime profile for the plugin).
+ </p>
+ </section>
+ <section name="Plugin Tools">
+ <p>By now, we've mentioned the plugin tools several times without telling
+ you what they are or how to use them. Instead of manually writing (and
+ maintaining) the metadata detailed above, Maven 2.0 ships with some
+ tools to aid in this task. In fact, the only thing a plugin developer
+ needs to do is declare his project to be a plugin from within the POM.
+ Once this is done, Maven will call the appropriate descriptor
+ generators, etc. to produce an artifact that is ready for use within
+ Maven builds. Optional metadata can be injected via Javadoc annotation
+ (and possibly JDK5 annotations in the future) as described above,
+ enabling richer interactions between the Mojo and the user. The
+ section below describes the changes to the POM which are necessary to
+ create plugin artifacts.</p>
+ </section>
+ <section name="Project Descriptor (POM) Requirements">
+ <p>From the POM, Maven plugin projects look quite similar to any other
+ project. For pure Java plugins, the differences are even smaller than
+ for script-based plugins. The following details the POM elements
+ which are necessary to build a Maven plugin artifact.</p>
+ <p>
+ <table>
+ <tr>
+ <th>POM Element</th>
+ <th>Required for Java Mojos?</th>
+ <th>Sample Declaration</th>
+ <th>Notes</th>
+ </tr>
+ <tr>
+ <td>packaging</td>
+ <td>Yes</td>
+ <td>
+ <code><packaging>maven-plugin</packaging></code>
+ </td>
+ <td>The POM must declare a packaging element which describes this
+ project as a Maven plugin project.</td>
+ </tr>
+ <tr>
+ <td>scriptSourceDirectory</td>
+ <td>No</td>
+ <td>
+ <code><scriptSourceDirectory>src/main/scripts</scriptSourceDirectory></code>
+ </td>
+ <td>In the case of script-based Mojos (which are not covered in
+ detail within this document), the POM must include an additional
+ element to distinguish script sources from (optional) Java
+ supporting classes. This element is <code>scriptSourceDirectory</code>,
+ inside the <code>build</code> section. This directory is included in the list
+ of resources which accompany any compiled code in the resulting
+ artifact. It is specified separately from the resources in the
+ build section to denote its special status as an alternate source
+ directory for scripts.</td>
+ </tr>
+ </table>
+ </p>
+ <p>After making the changes above, the developer can simply call
+ <br/>
+ <br/>
+ <code>mvn install</code>
+ <br/>
+ <br/>
+ to install the plugin to
+ the local repository. (Any of the other standard lifecycle targets like
+ package, deploy, etc. are also available in like fashion.)
+ </p>
+ </section>
+ <section name="Resources">
+ <p>This section simply gives a listing of pointers for more
+ information.</p>
+ <p>
+ <ul>
+ <li>M2 Plugin Overview [
+ <a
+ href="plugin-overview.html">link</a>
+ ]
+ </li>
+ <li>QDox Project (Javadoc annotations) [
+ <a
+ href="http://qdox.codehaus.org">link</a>
+ ]
+ </li>
+ </ul>
+ </p>
+ </section>
+ </body>
+</document>
Propchange: maven/site/trunk/src/site/xdoc/developers/mojo-api-specification.xml
------------------------------------------------------------------------------
svn:eol-style = native