Author: jdcasey
Date: Tue Jan 10 20:58:12 2006
New Revision: 367925

URL: http://svn.apache.org/viewcvs?rev=367925&view=rev
Log:
Corrected java plugin dev guide for updates to the plugin version manager, and 
added an ant plugin dev guide. Will link in the Ant dev guide next.

Added:
    
maven/site/trunk/src/site/apt/guides/plugin/guide-ant-plugin-development.apt   
(with props)
Modified:
    
maven/site/trunk/src/site/apt/guides/plugin/guide-java-plugin-development.apt

Added: 
maven/site/trunk/src/site/apt/guides/plugin/guide-ant-plugin-development.apt
URL: 
http://svn.apache.org/viewcvs/maven/site/trunk/src/site/apt/guides/plugin/guide-ant-plugin-development.apt?rev=367925&view=auto
==============================================================================
--- 
maven/site/trunk/src/site/apt/guides/plugin/guide-ant-plugin-development.apt 
(added)
+++ 
maven/site/trunk/src/site/apt/guides/plugin/guide-ant-plugin-development.apt 
Tue Jan 10 20:58:12 2006
@@ -0,0 +1,675 @@
+  ---
+  Guide to Developing Ant Plugins
+  ---
+  John Casey
+  ---
+  09 January 2006
+  ---
+
+~~ 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.
+
+~~ NOTE: This guide has been adapted from "Guide to Developing Java Plugins"
+~~ by Bob Allison.
+
+Introduction
+
+  The intent of this document is to help users learn to develop Maven plugins
+  using Ant.
+  
+  As of the 2.0.1 release, Maven supports Ant-driven plugins. These plugins
+  allow the invocation of Ant targets (specified in scripts embedded in the
+  plugin jar) at specific points in the build lifecycle. They can also inject
+  parameter values into the Ant project instances when a target is called.
+  
+*Conventions
+
+  In this guide, we'll use the standard Maven directory structure for projects,
+  to keep our POMs as simple as possible. It's important to note that this is
+  only a standard layout, not a requirement. The important locations for our
+  discussion are the following:
+  
++---+
+  /<project-root>
+  |
+  +- pom.xml
+  |
+  +- /src
+  |  |
+  |  +- /main
+  |  |  |
+  |  |  +- /scripts (source location for script-driven plugins)
+  |  |  |  |
+  ...
++---+
+  
+*Getting Started
+
+  We'll start with the simplest of all possible plugins. This plugin takes no
+  parameters, and will simply print a message out to the screen when invoked.
+  This should familiarize the reader with the basics of mapping Ant build 
scripts
+  to the Maven plugin framework. From there, we will gradually increase the
+  complexity of our plugin, adding parameters, interacting with standard 
project
+  locations, and binding to lifecycle phases. Finally, we'll see how a single 
Ant
+  build script can be mapped to multiple Maven mojos within the same plugin.
+  
+**Hello, World
+
+  Our first plugin will simply print "Hello, World" to the console.
+  
+***The Build Script
+
+  The elemental Ant-driven mojo consists of a simple Ant build script, a 
mapping
+  metadata file, and of course the plugin's POM. If our goal is to print 
"Hello, World", 
+  we might use an Ant build script that looks something like this:
+  
++---+
+hello.build.xml:
+--------------------------------
+
+  <!-- The specification of the "hello" default target here allows us to
+       simplify the mapping document for a single mojo, as below.
+  -->
+  <project default="hello">
+    <target name="hello">
+      <echo>Hello, World</echo>
+    </target>
+  </project>
++---+
+
+***The Mapping Document
+
+  Once we've created this build script, we need to tell Maven how to use it as 
a
+  plugin. This involves creating a mapping document. Note that where the build
+  script was named <<hello.build.xml>>, the mapping document is named 
+  <<hello.mojos.xml>>. The naming of these files is very important, as this is 
how
+  the plugin parser matches mapping documents to build scripts. It has the 
general
+  form:
+  
+  * <basename><<.build.xml>> - The Ant build script.
+  
+  * <basename><<.mojos.xml>> - The corresponding mapping document.
+  
+  []
+  
+  A simple mapping document used to wire the above build script into Maven's
+  plugin framework might look as follows:
+  
++---+
+hello.mojos.xml:
+------------------------------
+
+  <pluginMetadata>
+    <mojos>
+      <mojo>
+        <goal>hello</goal>
+        <description>
+          Say Hello, World.
+        </description>
+      </mojo>
+    </mojos>
+  </pluginMetadata>
++---+
+
+***The POM
+
+  Now that we have the build script and mapping document, we're ready to build
+  this plugin. However, in order to build, we need to provide a POM for our new
+  plugin. As it turns out, the POM required for an Ant-driven plugin is fairly
+  complex. This is because we have to configure the maven-plugin-plugin to use
+  the Ant plugin parsing tools in addition to the defaults (such as the Java
+  parsing tools). Our POM might look something like this:
+  
++---+
+pom.xml:
+------------------------------
+
+  <project>
+    <modelVersion>4.0.0</modelVersion>
+    
+    <groupId>org.myproject.plugins</groupId>
+    <artifactId>hello-plugin</artifactId>
+    <version>1.0-SNAPSHOT</version>
+    
+    <packaging>maven-plugin</packaging>
+    
+    <name>Hello Plugin</name>
+    
+    <build>
+      <plugins>
+        <plugin>
+          <!-- NOTE: We don't need groupId if the plugin's groupId is
+               org.apache.maven.plugins OR org.codehaus.mojo.
+               We also don't have to specify a version, since Maven can
+               automatically resolve the newest one.
+          -->
+          <artifactId>maven-plugin-plugin</artifactId>
+          
+          <!-- Add the Ant plugin tools -->
+          <dependencies>
+            <dependency>
+              <groupId>org.apache.maven</groupId>
+              <artifactId>maven-plugin-tools-ant</artifactId>
+              <version>2.0.1</version>
+            </dependency>
+          </dependencies>
+          
+          <!-- Tell the plugin-plugin which prefix we will use.
+               Later, we'll configure Maven to allow us to invoke this
+               plugin using the "prefix:mojo" shorthand.
+          -->
+          <configuration>
+            <prefix>hello</prefix>
+          </configuration>
+        </plugin>
+      </plugins>
+    </build>
+  </project>
++---+
+
+***Build It and Run It
+
+  Once we have a POM for our new plugin, we can install it into the local 
+  repository just as we would any other Maven project:
+  
++---+
+mvn install
++---+
+
+  and invoke it like this:
+  
++---+
+mvn org.myproject.plugins:hello-plugin:hello
++---+
+
+  This should output the following:
+  
++---+
+Hello, World
++---+
+
+*Using <<prefix:mojo>> Invocation Syntax
+
+  Our new plugin works, but look at that command line... The next thing is to
+  configure Maven so we can use the familiar <<prefix:mojo>> invocation syntax,
+  and leave that verbose, fully-qualified mess behind.
+  
+  As you know, Maven maps plugins to user-friendly prefixes. However, these
+  prefixes might overlap; that is, multiple plugins may try to use the same
+  prefix inadvertently. To avoid the obvious ambiguity associated with such
+  a collision, Maven will search a predetermined list of plugin groupIds for
+  a given prefix, with the first match winning. So, if we want to add our new
+  plugin to this search, we need to configure the list of plugin groupIds.
+  
+**Configuring Plugin-Prefix Searching
+
+  In order to reference our new plugin by prefix, we need to add its groupId to
+  the <<<\<pluginGroups/\>>>> list in the <<<settings.xml>>> file. As you 
probably
+  know, this file is usually found under $HOME/.m2. The added section to make 
our
+  plugin's groupId searchable should look like this:
+  
++---+
+~/.m2/settings.xml:
+------------------------------
+
+  <settings>
+    .
+    .
+    .
+    <pluginGroups>
+      <pluginGroup>org.myproject.plugins</pluginGroup>
+    </pluginGroups>
+    .
+    .
+    .
+  </settings>
++---+
+
+**Run It
+
+  We can check that this worked by invoking our new mojo once again, this time
+  using the prefix syntax:
+  
++---+
+mvn hello:hello
++---+  
+
+*Adding Plugin Parameters
+
+  Now, suppose it's not enough that our plugin display static text to the 
console.
+  Suppose we need it to display a greeting that is a little more personalized.
+  We can easily add support for this by adding a <<name>> parameter. For good 
measure,
+  we'll output the current project's name as well.
+  
+**Change the Ant Script
+
+  The build script will have to change to output the new information:
+  
++---+
+hello.build.xml:
+--------------------------------
+
+  <!-- The specification of the "hello" default target here allows us to
+       simplify the mapping document for a single mojo, as below.
+  -->
+  <project default="hello">
+    <target name="hello">
+      <echo>Hello, ${name}. You're building project: ${projectName}</echo>
+    </target>
+  </project>
++---+
+
+**Change the Mapping Document
+
+  Now that we have a build script which requires two new parameters, we have to
+  tell the mapping document about them, so they will be injected into the Ant
+  Project instance.
+  
++---+
+hello.mojos.xml:
+------------------------------
+
+  <pluginMetadata>
+    <mojos>
+      <mojo>
+        <goal>hello</goal>
+        <requiresProject>true</requiresProject>
+        
+        <description>
+          Say Hello, including the user's name, and print the project name to 
the console.
+        </description>
+        <parameters>
+          <parameter>
+            <name>name</name> 
+            <property>name</property> 
+            <required>true</required> 
+            <expression>${name}</expression>
+            <type>java.lang.String</type>
+            <description>The name of the user to greet.</description>
+          </parameter>
+          
+          <parameter>
+            <name>projectName</name> 
+            <property>projectName</property>
+            <required>true</required>
+            <readonly>true</readonly>
+            <defaultValue>${project.name}</defaultValue>
+            <type>java.lang.String</type>
+            <description>The name of the project currently being 
built.</description>
+          </parameter>
+        </parameters>
+      </mojo>
+    </mojos>
+  </pluginMetadata>
++---+
+
+  You'll notice several differences from the old version of the mapping 
document.
+  First, we've added <<requiresProject="true">> to the mojo declaration. This 
tells
+  Maven that our mojo requires a valid project before it can execute...in our 
case, 
+  we need a project so we can determine the correct <<projectName>> to use. 
Next,
+  we've added two parameter declarations to our mojo mapping; one for <<name>> 
and
+  another for <<projectName>>.
+  
+  The <<name>> parameter declaration provides an expression attribute...this
+  allows the user to specify <<<-Dname=somename>>> on the command line. 
Otherwise,
+  the only way to configure this parameter would be through a 
<<<\<configuration/\>>>>
+  element within the plugin specification in the user's POM. Note that this
+  parameter is required to have a value before our mojo can execute.
+  
+  The <<projectName>> parameter declaration provides two other interesting 
items.
+  First, it specifies a defaultValue attribute, which specifies an expression 
to
+  be evaluated against Maven's current build state in order to extract the 
parameter's
+  value. Second, it specifies a readonly attribute, which means the user cannot
+  directly configure this parameter - either via command line or configuration
+  within the POM. It can only be modified by modifying the build state 
referenced
+  in the defaultValue...in our case, the name element of the POM. Also note 
that
+  this parameter is declared to be required before our mojo can execute.
+
+**Rebuild It and Run It
+  
+  Now that we've modified our plugin, we have to rebuild it before running it 
again.
+  
++---+
+mvn clean install
++---+
+
+  Next, we should run the plugin again to verify that it's doing what we 
expect.
+  However, before we can run it, we have some requirements to satisfy. First, 
we
+  have to be sure we're executing in the context of a valid Maven 
POM...runnning
+  in the plugin's own project directory should satisfy that requirement. Then,
+  we have to satisfy the name requirement. We can do this directly through the
+  command line. So, the resulting invocation of our plugin will look like this:
+  
++---+
+mvn -Dname=<your-name-here> hello:hello
++---+
+
+  or, in my case:
+  
++---+
+mvn -Dname=John hello:hello
++---+
+
+  This should output the following:
+  
++---+
+Hello, John. You're building project: Hello Plugin
++---+
+
+*Defining Multiple Mojos from One Build Script
+
+  If you're familiar with Ant, you're probably familiar with the common usage
+  pattern of defining multiple build types within a single build script. For
+  instance, you might have a build type for cleaning the project, another for
+  producing the application jar file, and yet another for producing the full
+  distribution including javadocs, etc.
+  
+  The concept is pretty simple. Discrete chunks of the build process are 
separated
+  into targets within the script. These targets can reference one another in
+  order to make reuse within the build script possible.
+  
+  These same concepts map pretty well to Maven, actually. However, instead of
+  targets directly referencing one another, they would be bound to the 
appropriate
+  phases of the build lifecycle. In this way, multiple Ant targets from the 
same
+  build script can be reused piecemeal at different points in multiple build
+  lifecycles (clean, site, and the main lifecycle are three examples).
+  
+  This section will describe how to map multiple logical mojos onto different 
+  targets within the same Ant build script. It's also possible to reference
+  targets from multiple build scripts, but we'll cover this later.
+  
+**Two Targets, One Script
+
+  To test this, we'll split our echo statement into two targets. Then,
+  we'll reference each as separate mojos in the build. The new script
+  looks like this:
+  
++---+
+one-two.build.xml:
+--------------------------------
+
+  <!-- NOTE: The default target has been removed. This is no longer
+       needed, since we're going to use two independently mapped
+       mojos from this script.
+  -->
+  <project>
+    <target name="one">
+      <echo>Hello, ${name}.</echo>
+    </target>
+    
+    <target name="two">
+      <echo>You're building project: ${projectName}</echo>
+    </target>
+  </project>
++---+
+
+**Map the Mojos
+
+  Next, we'll modify our original mapping document to map these two new mojos
+  instead of the old one:
+  
++---+
+one-two.mojos.xml:
+------------------------------
+
+  <pluginMetadata>
+    <mojos>
+      <mojo>
+        <goal>one</goal>
+        <call>one</call>
+        
+        <description>
+          Say Hello. Include the user's name.
+        </description>
+        <parameters>
+          <parameter>
+            <name>name</name> 
+            <property>name</property> 
+            <required>true</required> 
+            <expression>${name}</expression>
+            <type>java.lang.String</type>
+            <description>The name of the user to greet.</description>
+          </parameter>
+        </parameters>
+      </mojo>
+          
+      <mojo>
+        <goal>two</goal>
+        <call>two</call>
+        <requiresProject>true</requiresProject>
+        
+        <description>
+          Write the project name to the console.
+        </description>
+        <parameters>
+          <parameter>
+            <name>projectName</name> 
+            <property>projectName</property>
+            <required>true</required>
+            <readonly>true</readonly>
+            <defaultValue>${project.name}</defaultValue>
+            <type>java.lang.String</type>
+            <description>The name of the project currently being 
built.</description>
+          </parameter>
+        </parameters>
+      </mojo>
+    </mojos>
+  </pluginMetadata>
++---+
+
+  Now that we've split the old functionality into two distinct mojos, there are
+  some interesting consequences. Aside from the obvious, mojo <<one>> no longer
+  requires a valid project instance in order to execute, since we only require 
+  the user's name in order to greet him.
+  
+  Aside from this, we've added a new <<\<call\>>> element for each mojo in the
+  mapping document. This element describes which Ant target should be called
+  when the mojo is invoked.
+  
+**Build It, Run It
+
+  Now that we have two separate mojos, we can execute them singly, or in any 
order
+  we choose. We can bind them to phases of the lifecycle using plugin 
configuration
+  inside the build element of a POM. We can execute them like this:
+  
++---+
+mvn -Dname=John hello:one
+
+RETURNS:
+
+Hello, John.
+
+
+mvn hello:two (executed in the plugin's project directory)
+
+RETURNS:
+
+You're building project: Hello Plugin
++---+
+
+  Alternatively, you could build a POM like this:
+  
++---+
+test-project/pom.xml:
+----------------------------
+
+  <project>
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.myproject.tests</groupId>
+    <artifactId>hello-plugin-tests</artifactId>
+    <version>1.0</version>
+    
+    <name>Test Project</name>
+    
+    <build>
+      <plugins>
+        <plugin>
+          <groupId>org.myproject.plugins</groupId>
+          <artifactId>hello-plugin</artifactId>
+          
+          <configuration>
+            <name>John</name>
+          </configuration>
+          
+          <executions>
+            <execution>
+              <phase>validate</phase>
+              <goals>
+                <goal>one</goal>
+                <goal>two</goal>
+              </goals>
+            </execution>
+          </executions>
+        </plugin>
+      </plugins>
+    </build>
+  </project>
++---+
+
+  Then, simply call Maven on this new POM:
+  
++---+
+cd test-project
+mvn validate
++---+
+
+  You should see the following output:
+  
++---+
+Hello, John.
+You're building project: Test Project
++---+
+
+**A Note on Multiple Build Scripts
+
+  It's worth mentioning that Ant-driven plugins can just as easily contain
+  multiple Ant build scripts. Simply follow the naming rules - naming each
+  A.build.xml, B.build.xml, C.build.xml, etc. for example - and be sure to
+  provide a mapping document to correspond to each build script that contains
+  a mojo (other build scripts may be contained in the plugin, and referenced 
+  by one of these; they don't need mapping documents). So, for the above 
examples
+  (assuming they all contained mojo targets), you'd need: A.mojos.xml, 
B.mojos.xml,
+  and C.mojos.xml. If C.build.xml was referenced by A and B, but didn't contain
+  mojo targets, then you don't need a C.mojos.xml for obvious reasons.
+
+*Advanced Usage
+
+  Below are some tips on some of the more advanced options related to Ant 
mojos.
+  
+**Component References
+
+  If your plugin needs a reference to a Plexus component, it will have to 
define
+  something similar to the following in the mapping document:
+  
++---+
+  <pluginMetadata>
+    <mojos>
+      <mojo>
+        .
+        .
+        .
+        <components>
+          <component>
+            <role>org.apache.maven.project.MavenProjectBuilder</role>
+            <hint>default</hint> <!-- This is optional -->
+          </component>
+        </components>
+        .
+        .
+        .
+      </mojo>
+    </mojos>
+  </pluginMetadata>
++---+
+
+**Forking New Lifecycles
+
+  In case your plugin needs to fork a new lifecycle, you can include the
+  following in the mapping document:
+  
++---+
+  <pluginMetadata>
+    <mojos>
+      <mojo>
+        .
+        .
+        .
+        <execute>
+          <lifecycle>my-custom-lifecycle</lifecycle>
+          <phase>package</phase>
+          
+          <!-- OR -->
+          
+          <goal>some:goal</goal>
+        </execute>
+        .
+        .
+        .
+      </mojo>
+    </mojos>
+  </pluginMetadata>
++---+
+
+**Deprecation
+
+  As time goes on, you will likely have to deprecate part of your plugin.
+  Whether it's a mojo parameter, or even an entire mojo, Maven can support
+  it, and remind your users that the mojo or configuration they're using is
+  deprecated, and print a message directing them to adjust their usage.
+  
+  To deprecate a mojo parameter, simply add this:
+  
++---+
+  <pluginMetadata>
+    <mojos>
+      <mojo>
+        .
+        .
+        .
+        <parameters>
+          <parameter>
+            .
+            .
+            .
+            <deprecated>Use this other parameter instead.</deprecated>
+            .
+            .
+            .
+          </parameter>
+        </parameters>
+        .
+        .
+        .
+      </mojo>
+    </mojos>
+  </pluginMetadata>
++---+
+
+  To deprecate an entire mojo, add this:
+  
++---+
+  <pluginMetadata>
+    <mojos>
+      <mojo>
+        .
+        .
+        .
+        <deprecated>Use this other mojo instead.</deprecated>
+        .
+        .
+        .
+      </mojo>
+    </mojos>
+  </pluginMetadata>
++---+

Propchange: 
maven/site/trunk/src/site/apt/guides/plugin/guide-ant-plugin-development.apt
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
maven/site/trunk/src/site/apt/guides/plugin/guide-ant-plugin-development.apt
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Modified: 
maven/site/trunk/src/site/apt/guides/plugin/guide-java-plugin-development.apt
URL: 
http://svn.apache.org/viewcvs/maven/site/trunk/src/site/apt/guides/plugin/guide-java-plugin-development.apt?rev=367925&r1=367924&r2=367925&view=diff
==============================================================================
--- 
maven/site/trunk/src/site/apt/guides/plugin/guide-java-plugin-development.apt 
(original)
+++ 
maven/site/trunk/src/site/apt/guides/plugin/guide-java-plugin-development.apt 
Tue Jan 10 20:58:12 2006
@@ -167,15 +167,25 @@
 
 *** Shortening the Command Line
 
-  It is possible to shorten the amount of typing needed on the command
-  line.  To do this, you need to install the plugin with the
-  <<<updateReleaseInfo>>> option set to true; for example:
+~~ [jdcasey; 10-Jan-2006]
+~~
+~~ I'm commenting this out, since it's obsolete. The plugin version
+~~ manager now checks LATEST metadata before it checks RELEASE metadata.
+~~ Since LATEST metadata is _always_ published for plugins, nothing
+~~ special needs to be done for the prefix matching to work.
+~~
+~~  It is possible to shorten the amount of typing needed on the command
+~~  line.  To do this, you need to install the plugin with the
+~~  <<<updateReleaseInfo>>> option set to true; for example:
+~~ 
+~~ +----+
+~~ mvn -DupdateReleaseInfo=true install
+~~ +----+
+~~ 
+~~  You also need to add your plugin's group ID to the list of group IDs
 
-+----+
-mvn -DupdateReleaseInfo=true install
-+----+
-
-  You also need to add your plugin's group ID to the list of group IDs
+  In order to shorten the amount of typing needed on the command line,
+  you will need to add your plugin's group ID to the list of group IDs
   searched by default.  To do this, you need to add the following to
   your <<<settings.xml>>> file:
 


Reply via email to