PR: MNG-817

add goal="..." to @execute

git-svn-id: https://svn.apache.org/repos/asf/maven/components/trunk@292125 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Brett Leslie Porter 2005-09-28 05:09:14 +00:00
parent 86d1a481f5
commit ddfcc65d55
11 changed files with 657 additions and 360 deletions

View File

@ -0,0 +1,54 @@
package org.apache.maven.plugin.coreit;
/*
* 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.
*/
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProject;
/**
* @goal fork-goal
*
* @execute goal="touch"
*/
public class CoreItGoalForkerMojo
extends AbstractMojo
{
/**
* @parameter expression="${project}"
*/
private MavenProject project;
/**
* @parameter expression="${executedProject}"
*/
private MavenProject executedProject;
public void execute()
throws MojoExecutionException
{
if ( !executedProject.getBuild().getFinalName().equals( "coreitified" ) )
{
throw new MojoExecutionException( "Unexpected result, final name of executed project is " + executedProject.getBuild().getFinalName() );
}
if ( project.getBuild().getFinalName().equals( "coreitified" ) )
{
throw new MojoExecutionException( "forked project was polluted" );
}
}
}

View File

@ -487,7 +487,7 @@ public class DefaultLifecycleExecutor
MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
if ( mojoDescriptor.getExecutePhase() != null )
if ( mojoDescriptor.getExecutePhase() != null || mojoDescriptor.getExecuteGoal() != null )
{
forkLifecycle( mojoDescriptor, session, project );
}
@ -661,73 +661,83 @@ public class DefaultLifecycleExecutor
String targetPhase = mojoDescriptor.getExecutePhase();
// Create new lifecycle
Map lifecycleMappings = constructLifecycleMappings( session, targetPhase, project );
String executeLifecycle = mojoDescriptor.getExecuteLifecycle();
if ( executeLifecycle != null )
Map lifecycleMappings = null;
if ( targetPhase != null )
{
Lifecycle lifecycleOverlay;
try
{
lifecycleOverlay = mojoDescriptor.getPluginDescriptor().getLifecycleMapping( executeLifecycle );
}
catch ( IOException e )
{
throw new LifecycleExecutionException( "Unable to read lifecycle mapping file", e );
}
catch ( XmlPullParserException e )
{
throw new LifecycleExecutionException( "Unable to parse lifecycle mapping file", e );
}
// Create new lifecycle
lifecycleMappings = constructLifecycleMappings( session, targetPhase, project );
if ( lifecycleOverlay == null )
String executeLifecycle = mojoDescriptor.getExecuteLifecycle();
if ( executeLifecycle != null )
{
throw new LifecycleExecutionException( "Lifecycle '" + executeLifecycle + "' not found in plugin" );
}
for ( Iterator i = lifecycleOverlay.getPhases().iterator(); i.hasNext(); )
{
Phase phase = (Phase) i.next();
for ( Iterator j = phase.getExecutions().iterator(); j.hasNext(); )
Lifecycle lifecycleOverlay;
try
{
Execution e = (Execution) j.next();
lifecycleOverlay = mojoDescriptor.getPluginDescriptor().getLifecycleMapping( executeLifecycle );
}
catch ( IOException e )
{
throw new LifecycleExecutionException( "Unable to read lifecycle mapping file", e );
}
catch ( XmlPullParserException e )
{
throw new LifecycleExecutionException( "Unable to parse lifecycle mapping file", e );
}
for ( Iterator k = e.getGoals().iterator(); k.hasNext(); )
if ( lifecycleOverlay == null )
{
throw new LifecycleExecutionException( "Lifecycle '" + executeLifecycle + "' not found in plugin" );
}
for ( Iterator i = lifecycleOverlay.getPhases().iterator(); i.hasNext(); )
{
Phase phase = (Phase) i.next();
for ( Iterator j = phase.getExecutions().iterator(); j.hasNext(); )
{
String goal = (String) k.next();
MojoDescriptor desc = mojoDescriptor.getPluginDescriptor().getMojo( goal );
Execution e = (Execution) j.next();
if ( desc == null )
for ( Iterator k = e.getGoals().iterator(); k.hasNext(); )
{
String message = "Required goal '" + goal + "' not found in plugin '" +
mojoDescriptor.getPluginDescriptor().getGoalPrefix() + "'";
int index = goal.indexOf( ':' );
if ( index >= 0 )
{
String prefix = goal.substring( index + 1 );
if ( prefix.equals( mojoDescriptor.getPluginDescriptor().getGoalPrefix() ) )
{
message = message + " (goals should not be prefixed - try '" + prefix + "')";
}
}
throw new LifecycleExecutionException( message );
}
String goal = (String) k.next();
MojoDescriptor desc = mojoDescriptor.getPluginDescriptor().getMojo( goal );
MojoExecution mojoExecution = new MojoExecution( desc, (Xpp3Dom) e.getConfiguration() );
addToLifecycleMappings( lifecycleMappings, phase.getId(), mojoExecution,
session.getSettings() );
if ( desc == null )
{
String message = "Required goal '" + goal + "' not found in plugin '" +
mojoDescriptor.getPluginDescriptor().getGoalPrefix() + "'";
int index = goal.indexOf( ':' );
if ( index >= 0 )
{
String prefix = goal.substring( index + 1 );
if ( prefix.equals( mojoDescriptor.getPluginDescriptor().getGoalPrefix() ) )
{
message = message + " (goals should not be prefixed - try '" + prefix + "')";
}
}
throw new LifecycleExecutionException( message );
}
MojoExecution mojoExecution = new MojoExecution( desc, (Xpp3Dom) e.getConfiguration() );
addToLifecycleMappings( lifecycleMappings, phase.getId(), mojoExecution,
session.getSettings() );
}
}
}
}
removeFromLifecycle( mojoDescriptor, lifecycleMappings );
}
removeFromLifecycle( mojoDescriptor, lifecycleMappings );
MavenProject executionProject = new MavenProject( project );
executeGoalWithLifecycle( targetPhase, session, lifecycleMappings, executionProject );
if ( targetPhase != null )
{
executeGoalWithLifecycle( targetPhase, session, lifecycleMappings, executionProject );
}
else
{
executeStandaloneGoal( mojoDescriptor.getExecuteGoal(), session, executionProject );
}
project.setExecutionProject( executionProject );
}
private void removeFromLifecycle( MojoDescriptor mojoDescriptor, Map lifecycleMappings )

View File

@ -58,6 +58,8 @@ public class MojoDescriptor
private String executePhase;
private String executeGoal;
private String executeLifecycle;
private String deprecated;
@ -425,4 +427,14 @@ public class MojoDescriptor
{
this.requiresReports = requiresReports;
}
public void setExecuteGoal( String executeGoal )
{
this.executeGoal = executeGoal;
}
public String getExecuteGoal()
{
return executeGoal;
}
}

View File

@ -142,6 +142,13 @@ public class PluginDescriptorBuilder
mojo.setExecutePhase( executePhase );
}
String executeMojo = c.getChild( "executeGoal" ).getValue();
if ( executeMojo != null )
{
mojo.setExecuteGoal( executeMojo );
}
String executeLifecycle = c.getChild( "executeLifecycle" ).getValue();
if ( executeLifecycle != null )

View File

@ -177,6 +177,11 @@ public class PluginDescriptorGenerator
element( w, "executePhase", mojoDescriptor.getExecutePhase() );
}
if ( mojoDescriptor.getExecuteGoal() != null )
{
element( w, "executeGoal", mojoDescriptor.getExecuteGoal() );
}
if ( mojoDescriptor.getExecuteLifecycle() != null )
{
element( w, "executeLifecycle", mojoDescriptor.getExecuteLifecycle() );

View File

@ -15,6 +15,7 @@ this.descriptionPattern = Pattern.compile( "(?s)\\r?\\n\\s*\\*" );
this.typePattern = Pattern.compile( "type\\s*=\\s*\"(.*?)\"" );
this.expressionPattern = Pattern.compile( "expression\\s*=\\s*\"(.*?)\"" );
this.phasePattern = Pattern.compile( "phase\\s*=\\s*\"(.*?)\"" );
this.goalPattern = Pattern.compile( "goal\\s*=\\s*\"(.*?)\"" );
this.lifecyclePattern = Pattern.compile( "lifecycle\\s*=\\s*\"(.*?)\"" );
this.rolePattern = Pattern.compile( "role\\s*=\\s*\"(.*?)\"" );
this.roleHintPattern = Pattern.compile( "roleHint\\s*=\\s*\"(.*?)\"" );
@ -182,15 +183,31 @@ extract( file, mojoDescriptor )
{
mojoDescriptor.setExecutePhase( m.group( 1 ) );
}
else
m = goalPattern.matcher( value );
if ( m.find() )
{
throw new InvalidPluginDescriptorException( "@execute must have a phase" );
mojoDescriptor.setExecuteGoal( m.group( 1 ) );
}
if ( mojoDescriptor.getExecutePhase() == null || mojoDescriptor.getExecuteGoal() == null )
{
throw new InvalidPluginDescriptorException( "@execute must have a phase or goal" );
}
if ( mojoDescriptor.getExecutePhase() != null && mojoDescriptor.getExecuteGoal() != null )
{
throw new InvalidPluginDescriptorException( "@execute must have only one of a phase or goal" );
}
m = lifecyclePattern.matcher( value );
if ( m.find() )
{
mojoDescriptor.setExecuteLifecycle( m.group( 1 ) );
if ( mojoDescriptor.getExecuteGoal() != null )
{
throw new InvalidPluginDescriptorException( "@execute lifecycle requires a phase instead of a goal" );
}
}
}
}

View File

@ -217,18 +217,30 @@ public class JavaMojoDescriptorExtractor
if ( execute != null )
{
String executePhase = execute.getNamedParameter( "phase" );
String executeGoal = execute.getNamedParameter( "goal" );
if ( executePhase == null )
if ( executePhase == null && executeGoal == null )
{
throw new InvalidPluginDescriptorException( "@execute tag requires a 'phase' parameter" );
throw new InvalidPluginDescriptorException( "@execute tag requires a 'phase' or 'goal' parameter" );
}
else if ( executePhase != null && executeGoal != null )
{
throw new InvalidPluginDescriptorException(
"@execute tag can have only one of a 'phase' or 'goal' parameter" );
}
mojoDescriptor.setExecutePhase( executePhase );
mojoDescriptor.setExecuteGoal( executeGoal );
String lifecycle = execute.getNamedParameter( "lifecycle" );
if ( lifecycle != null )
{
mojoDescriptor.setExecuteLifecycle( lifecycle );
if ( mojoDescriptor.getExecuteGoal() != null )
{
throw new InvalidPluginDescriptorException(
"@execute lifecycle requires a phase instead of a goal" );
}
}
}

View File

@ -29,18 +29,18 @@
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-tools-api</artifactId>
<version>2.0-beta-2</version>
<version>2.0-beta-3-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-tools-java</artifactId>
<version>2.0-beta-2</version>
<version>2.0-beta-3-SNAPSHOT</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-tools-beanshell</artifactId>
<version>2.0-beta-2</version>
<version>2.0-beta-3-SNAPSHOT</version>
<scope>runtime</scope>
</dependency>
<dependency>
@ -48,11 +48,5 @@
<artifactId>maven-reporting-impl</artifactId>
<version>2.0-beta-3-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-tools-marmalade</artifactId>
<version>2.0-beta-2</version>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>
</project>

View File

@ -0,0 +1,35 @@
package org.apache.maven.script.marmalade.tags;
/*
* Copyright 2001-2005 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.
*/
import org.codehaus.marmalade.runtime.MarmaladeExecutionException;
/**
* @author jdcasey Created on Feb 8, 2005
*/
public class ExecuteGoalTag
extends AbstractStringValuedBodyTag
{
protected void setValue( String value )
throws MarmaladeExecutionException
{
MetadataTag metadataTag = (MetadataTag) requireParent( MetadataTag.class );
metadataTag.setExecuteGoal( value );
}
}

View File

@ -59,6 +59,8 @@ public class MetadataTag
private String executePhase;
private String executeGoal;
private String executeLifecycle;
private String lifecyclePhase;
@ -121,6 +123,11 @@ public class MetadataTag
descriptor.setExecutePhase( executePhase );
}
if ( notEmpty( executeGoal ) )
{
descriptor.setExecutePhase( executeGoal );
}
if ( notEmpty( lifecyclePhase ) )
{
descriptor.setPhase( lifecyclePhase );
@ -236,4 +243,9 @@ public class MetadataTag
{
this.requiresReports = requiresReports;
}
public void setExecuteGoal( String executeGoal )
{
this.executeGoal = executeGoal;
}
}

View File

@ -24,16 +24,16 @@
</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 (currently just marmalade - we are
working to implement others). 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
<p>Starting with Maven 2.0, plugins can be written in Java or any of a
number of scripting languages (currently just marmalade - we are
working to implement others). 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
<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
<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
@ -50,92 +50,119 @@
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
--> 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)
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 trigger's 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>This interface forms the contract required for Mojos to interact
with the Maven infrastructure. It features an
<code>execute()</code>
method, which trigger's 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
<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>
<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>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>
<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
<p>Inject a standard Maven logging mechanism to allow this Mojo
to communicate events and feedback to the user.</p>
</li>
<li>
@ -143,132 +170,179 @@
<p>
<b>[IMPLEMENTED]</b>
</p>
<p>Furnish access to the standard Maven logging mechanism which
<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>
<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>
<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>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>
<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>
<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>
<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>
<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>
<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>
<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>
<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>
<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>
<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>
<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>
<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>
<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 it's 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
<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 it's 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 &lt;rawAnnotationValue&gt;)</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>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 &lt;rawAnnotationValue&gt;)</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>
@ -279,26 +353,36 @@
<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>
<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>
<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
<p>Each Mojo specified inside a plugin descriptor must provide the
following (annotations specified here are at the class level):</p>
<p>
<table>
@ -312,97 +396,121 @@
<td>goal</td>
<td>@goal &lt;goalName&gt;</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
<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
<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 (marmalade, java,
<td>No. Default:
<code>java</code>
</td>
<td>The implementation language for this Mojo (marmalade, java,
beanshell, etc.).</td>
</tr>
<tr>
<td>configurator</td>
<td>@configurator &lt;roleHint&gt;</td>
<td>No</td>
<td>The configurator type to use when injecting parameter values
into this Mojo. The value is normally deduced from the
<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>
<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 &lt;phaseName&gt;</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>
<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>executePhase</td>
<td>@executePhase &lt;phaseName&gt;</td>
<td>execute</td>
<td>@execute [phase=&lt;phaseName&gt;|goal=&lt;goalName&gt;] [lifecycle=&lt;lifecycleId&gt;]</td>
<td>No</td>
<td>When this Mojo's goal is invoked directly from the command
line, <b>executePhase</b> specifies the last phase in the
standard build lifecycle to execute before this Mojo
executes.</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="/lifecycle.html">build lifecycle</a>
.
</td>
</tr>
<tr>
<td>requiresDependencyResolution</td>
<td>@requiresDependencyResolution &lt;requiredScope&gt;</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>
<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>
<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>
<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 to be able to work
with. 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
<p>Each Mojo specifies the parameters that it expects to be able to work
with. 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
<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
<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>
@ -416,122 +524,137 @@
<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>
<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
<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>
<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>
<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
&lt;build&gt;&lt;finalName/&gt;&lt;/build&gt; 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>
<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
&lt;build&gt;&lt;finalName/&gt;&lt;/build&gt; 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>
<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 ${&lt;name&gt;} 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>
<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 ${&lt;name&gt;} 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>
<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 it's 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 &lt;scope&gt; element (all dependencies in the
plugin descriptor are assumed to be runtime, because this is a
runtime profile for the plugin).</p>
<p>The final component of a plugin descriptor is the dependencies. This
enables the plugin to function independently of it's 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 &lt;scope&gt; 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
<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
<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>
@ -544,40 +667,56 @@
<tr>
<td>packaging</td>
<td>Yes</td>
<td><code>&lt;packaging&gt;maven-plugin&lt;/packaging&gt;</code></td>
<td>The POM must declare a packaging element which describes this
<td>
<code>&lt;packaging&gt;maven-plugin&lt;/packaging&gt;</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>&lt;scriptSourceDirectory&gt;src/main/scripts&lt;/scriptSourceDirectory&gt;</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 the scriptSourceDirectory,
inside the build 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
<td>
<code>&lt;scriptSourceDirectory&gt;src/main/scripts&lt;/scriptSourceDirectory&gt;</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 the scriptSourceDirectory,
inside the build 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>m2 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>
<p>After making the changes above, the developer can simply call
<br/>
<br/>
<code>m2 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
<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>
<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>