You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by be...@apache.org on 2008/08/09 01:40:18 UTC

svn commit: r684144 - in /maven/plugins/trunk/maven-invoker-plugin/src: main/java/org/apache/maven/plugin/invoker/ site/ site/apt/ site/apt/examples/ test/java/org/apache/maven/plugin/invoker/

Author: bentmann
Date: Fri Aug  8 16:40:17 2008
New Revision: 684144

URL: http://svn.apache.org/viewvc?rev=684144&view=rev
Log:
[MINVOKER-46] Allow multiple invocations of Maven on the same project

Added:
    maven/plugins/trunk/maven-invoker-plugin/src/site/apt/examples/invoker-properties.apt.vm   (with props)
Modified:
    maven/plugins/trunk/maven-invoker-plugin/src/main/java/org/apache/maven/plugin/invoker/InvokerMojo.java
    maven/plugins/trunk/maven-invoker-plugin/src/site/apt/index.apt
    maven/plugins/trunk/maven-invoker-plugin/src/site/site.xml
    maven/plugins/trunk/maven-invoker-plugin/src/test/java/org/apache/maven/plugin/invoker/InvokerMojoTest.java

Modified: maven/plugins/trunk/maven-invoker-plugin/src/main/java/org/apache/maven/plugin/invoker/InvokerMojo.java
URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-invoker-plugin/src/main/java/org/apache/maven/plugin/invoker/InvokerMojo.java?rev=684144&r1=684143&r2=684144&view=diff
==============================================================================
--- maven/plugins/trunk/maven-invoker-plugin/src/main/java/org/apache/maven/plugin/invoker/InvokerMojo.java (original)
+++ maven/plugins/trunk/maven-invoker-plugin/src/main/java/org/apache/maven/plugin/invoker/InvokerMojo.java Fri Aug  8 16:40:17 2008
@@ -61,7 +61,6 @@
 import org.codehaus.plexus.util.ReaderFactory;
 import org.codehaus.plexus.util.StringUtils;
 import org.codehaus.plexus.util.WriterFactory;
-import org.codehaus.plexus.util.cli.CommandLineException;
 import org.codehaus.plexus.interpolation.InterpolationException;
 import org.codehaus.plexus.interpolation.Interpolator;
 import org.codehaus.plexus.interpolation.MapBasedValueSource;
@@ -378,7 +377,10 @@
      * <pre>
      * # A comma or space separated list of goals/phases to execute, may
      * # specify an empty list to execute the default goal of the IT project
-     * invoker.goals=clean package site
+     * invoker.goals=clean install
+     * 
+     * # Optionally, a list of goals to run during further invocations of Maven
+     * invoker.goals.2=${project.groupId}:${project.artifactId}:${project.version}:run
      * 
      * # A comma or space separated list of profiles to activate
      * invoker.profiles=its,jdk15
@@ -486,6 +488,16 @@
             projectsDir = cloneProjectsTo;
         }
 
+        if ( localRepositoryPath != null )
+        {
+            getLog().debug( "Using local repository: " + localRepositoryPath );
+
+            if ( !localRepositoryPath.exists() )
+            {
+                localRepositoryPath.mkdirs();
+            }
+        }
+
         final List failures = new ArrayList();
 
         for ( int i = 0; i < includedPoms.length; i++ )
@@ -495,7 +507,6 @@
             runBuild( projectsDir, pom, failures );
         }
 
-
         if ( !suppressSummaries )
         {
             final StringBuffer summary = new StringBuffer();
@@ -744,6 +755,10 @@
             }
         }
 
+        List goals = getGoals( basedir );
+
+        List profiles = getProfiles( basedir );
+
         Properties systemProperties = getTestProperties( basedir );
 
         FileLogger logger = setupLogger( basedir );
@@ -760,44 +775,27 @@
 
             final InvocationRequest request = new DefaultInvocationRequest();
 
-            final List invocationGoals = getGoals( basedir );
-
-            if ( invocationGoals.isEmpty()
-                || ( invocationGoals.size() == 1 && "_default".equals( invocationGoals.get( 0 ) ) ) )
+            if ( localRepositoryPath != null )
             {
-                getLog().debug( "Executing default goal for project in: " + project );
+                request.setLocalRepositoryDirectory( localRepositoryPath );
             }
-            else
-            {
-                getLog().debug( "Executing goals: " + invocationGoals + " for project in: " + project );
 
-                request.setGoals( invocationGoals );
+            if ( settingsFile != null )
+            {
+                File interpolatedSettingsFile =
+                    new File( settingsFile.getParentFile(), "interpolated-" + settingsFile.getName() );
+                buildInterpolatedFile( settingsFile, interpolatedSettingsFile );
+                request.setUserSettingsFile( interpolatedSettingsFile );
             }
 
             request.setProperties( systemProperties );
 
-            if ( localRepositoryPath != null )
-            {
-                File localRepoDir = localRepositoryPath;
-
-                getLog().debug( "Using local repository: " + localRepoDir );
-
-                if ( ! localRepositoryPath.exists() )
-                {
-                    localRepositoryPath.mkdirs();
-                }
-                
-                request.setLocalRepositoryDirectory( localRepoDir );
-            }
-
             request.setInteractive( false );
 
             request.setShowErrors( showErrors );
 
             request.setDebug( debug );
 
-            request.setBaseDirectory( basedir );
-
             if ( logger != null )
             {
                 request.setErrorHandler( logger );
@@ -805,98 +803,108 @@
                 request.setOutputHandler( logger );
             }
 
+            request.setBaseDirectory( basedir );
+
             if ( pomFile != null )
             {
                 request.setPomFile( pomFile );
             }
 
-            request.setProfiles( getProfiles( basedir ) );
-
-            if ( settingsFile != null )
+            for ( int invocationIndex = 1;; invocationIndex++ )
             {
-                File interpolatedSettingsFile =
-                    new File( settingsFile.getParentFile(), "interpolated-" + settingsFile.getName() );
-                buildInterpolatedFile( settingsFile, interpolatedSettingsFile );
-                request.setUserSettingsFile( interpolatedSettingsFile );
-            }
+                if ( invocationIndex > 1
+                    && invokerProperties.getProperty( "invoker.goals." + invocationIndex ) == null )
+                {
+                    break;
+                }
 
-            request.setMavenOpts( mavenOpts );
+                request.setGoals( goals );
 
-            configureInvocation( request, invokerProperties );
+                request.setProfiles( profiles );
 
-            try
-            {
-                getLog().debug( "Using MAVEN_OPTS: " + request.getMavenOpts() );
-                getLog().debug( "Executing: " + new MavenCommandLineBuilder().build( request ) );
-            }
-            catch ( CommandLineConfigurationException e )
-            {
-                getLog().debug( "Failed to display command line: " + e.getMessage() );
-            }
+                request.setMavenOpts( mavenOpts );
 
-            InvocationResult result = null;
+                configureInvocation( request, invocationIndex, invokerProperties );
 
-            try
-            {
-                result = invoker.execute( request );
-            }
-            catch ( final MavenInvocationException e )
-            {
-                getLog().debug( "Error invoking Maven: " + e.getMessage(), e );
-                getLog().info( "...FAILED[error invoking Maven]" );
+                try
+                {
+                    getLog().debug( "Using MAVEN_OPTS: " + request.getMavenOpts() );
+                    getLog().debug( "Executing: " + new MavenCommandLineBuilder().build( request ) );
+                }
+                catch ( CommandLineConfigurationException e )
+                {
+                    getLog().debug( "Failed to display command line: " + e.getMessage() );
+                }
 
-                failures.add( project );
+                InvocationResult result;
 
-                return;
-            }
+                try
+                {
+                    result = invoker.execute( request );
+                }
+                catch ( final MavenInvocationException e )
+                {
+                    getLog().debug( "Error invoking Maven: " + e.getMessage(), e );
+                    getLog().info( "...FAILED[error invoking Maven]" );
 
-            final CommandLineException executionException = result.getExecutionException();
-            final boolean nonZeroExit =
-                "failure".equalsIgnoreCase( invokerProperties.getProperty( "invoker.buildResult" ) );
+                    failures.add( project );
 
-            if ( executionException != null )
-            {
-                if ( !suppressSummaries )
-                {
-                    StringBuffer buffer = new StringBuffer( 256 );
-                    buffer.append( "...FAILED. " );
-                    if ( logger != null )
-                    {
-                        buffer.append( "See " );
-                        buffer.append( logger.getOutputFile().getAbsolutePath() );
-                        buffer.append( " for details." );
-                    }
-                    else
-                    {
-                        buffer.append( "See console output for details." );
-                    }
-                    getLog().info( buffer.toString() );
+                    return;
                 }
 
-                failures.add( project );
-            }
-            else if ( ( result.getExitCode() != 0 ) != nonZeroExit )
-            {
-                if ( !suppressSummaries )
+                final boolean nonZeroExit =
+                    "failure".equalsIgnoreCase( getInvokerProperty( invokerProperties, "invoker.buildResult",
+                                                                    invocationIndex ) );
+
+                if ( result.getExecutionException() != null )
                 {
-                    StringBuffer buffer = new StringBuffer( 256 );
-                    buffer.append( "...FAILED[code=" ).append( result.getExitCode() ).append( "]. " );
-                    if ( logger != null )
+                    if ( !suppressSummaries )
                     {
-                        buffer.append( "See " );
-                        buffer.append( logger.getOutputFile().getAbsolutePath() );
-                        buffer.append( " for details." );
+                        StringBuffer buffer = new StringBuffer( 256 );
+                        buffer.append( "...FAILED. " );
+                        if ( logger != null )
+                        {
+                            buffer.append( "See " );
+                            buffer.append( logger.getOutputFile().getAbsolutePath() );
+                            buffer.append( " for details." );
+                        }
+                        else
+                        {
+                            buffer.append( "See console output for details." );
+                        }
+                        getLog().info( buffer.toString() );
                     }
-                    else
+
+                    failures.add( project );
+
+                    return;
+                }
+                else if ( ( result.getExitCode() != 0 ) != nonZeroExit )
+                {
+                    if ( !suppressSummaries )
                     {
-                        buffer.append( "See console output for details." );
+                        StringBuffer buffer = new StringBuffer( 256 );
+                        buffer.append( "...FAILED[code=" ).append( result.getExitCode() ).append( "]. " );
+                        if ( logger != null )
+                        {
+                            buffer.append( "See " );
+                            buffer.append( logger.getOutputFile().getAbsolutePath() );
+                            buffer.append( " for details." );
+                        }
+                        else
+                        {
+                            buffer.append( "See console output for details." );
+                        }
+                        getLog().info( buffer.toString() );
                     }
-                    getLog().info( buffer.toString() );
-                }
 
-                failures.add( project );
+                    failures.add( project );
+
+                    return;
+                }
             }
-            else if ( !verify( basedir, logger ) )
+
+            if ( !verify( basedir, logger ) )
             {
                 if ( !suppressSummaries )
                 {
@@ -1529,42 +1537,66 @@
      * invoker properties will be left unchanged in the invocation request.
      * 
      * @param request The invocation request to configure, must not be <code>null</code>.
+     * @param index The one-based index of the invocation to configure, must be positive.
      * @param properties The invoker properties used to configure the invocation, must not be <code>null</code>.
-     * @return The configured invocation request.
      */
-    private InvocationRequest configureInvocation( InvocationRequest request, Properties properties )
+    private void configureInvocation( InvocationRequest request, int index, Properties properties )
     {
-        String goals = properties.getProperty( "invoker.goals" );
+        if ( index < 1 )
+        {
+            throw new IllegalArgumentException( "invalid invocation index: " + index );
+        }
+
+        String goals = getInvokerProperty( properties, "invoker.goals", index );
         if ( goals != null )
         {
             request.setGoals( new ArrayList( Arrays.asList( goals.split( "[,\\s]+" ) ) ) );
         }
 
-        String profiles = properties.getProperty( "invoker.profiles" );
+        String profiles = getInvokerProperty( properties, "invoker.profiles", index );
         if ( profiles != null )
         {
             request.setProfiles( new ArrayList( Arrays.asList( profiles.split( "[,\\s]+" ) ) ) );
         }
 
-        String opts = properties.getProperty( "invoker.mavenOpts" );
-        if ( opts != null )
+        String mvnOpts = getInvokerProperty( properties, "invoker.mavenOpts", index );
+        if ( mvnOpts != null )
         {
-            request.setMavenOpts( opts );
+            request.setMavenOpts( mvnOpts );
         }
 
-        String failureBehavior = properties.getProperty( "invoker.failureBehavior" );
+        String failureBehavior = getInvokerProperty( properties, "invoker.failureBehavior", index );
         if ( failureBehavior != null )
         {
             request.setFailureBehavior( failureBehavior );
         }
 
-        String nonRecursive = properties.getProperty( "invoker.nonRecursive" );
+        String nonRecursive = getInvokerProperty( properties, "invoker.nonRecursive", index );
         if ( nonRecursive != null )
         {
             request.setRecursive( !Boolean.valueOf( nonRecursive ).booleanValue() );
         }
+    }
 
-        return request;
+    /**
+     * Gets a value from the invoker properties. The invoker properties are intended to describe the invocation settings
+     * for multiple builds of the same project. For this reason, the properties are indexed. First, a property named
+     * <code>key.index</code> will be queried. If this property does not exist, the value of the property named
+     * <code>key</code> will finally be returned.
+     * 
+     * @param properties The invoker properties from which to lookup the value, must not be <code>null</code>.
+     * @param key The (base) key for the invoker property to lookup, must not be <code>null</code>.
+     * @param index The index of the invocation for which to retrieve the value, must not be negative.
+     * @return The value for the requested invoker property or <code>null</code> if not defined.
+     */
+    static String getInvokerProperty( Properties properties, String key, int index )
+    {
+        String value = properties.getProperty( key + '.' + index );
+        if ( value == null )
+        {
+            value = properties.getProperty( key );
+        }
+        return value;
     }
 
 }

Added: maven/plugins/trunk/maven-invoker-plugin/src/site/apt/examples/invoker-properties.apt.vm
URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-invoker-plugin/src/site/apt/examples/invoker-properties.apt.vm?rev=684144&view=auto
==============================================================================
--- maven/plugins/trunk/maven-invoker-plugin/src/site/apt/examples/invoker-properties.apt.vm (added)
+++ maven/plugins/trunk/maven-invoker-plugin/src/site/apt/examples/invoker-properties.apt.vm Fri Aug  8 16:40:17 2008
@@ -0,0 +1,109 @@
+ ------
+ Invoker Properties
+ ------
+ Benjamin Bentmann
+ ------
+ 2008-08-09
+ ------
+
+ ~~ Licensed to the Apache Software Foundation (ASF) under one
+ ~~ or more contributor license agreements.  See the NOTICE file
+ ~~ distributed with this work for additional information
+ ~~ regarding copyright ownership.  The ASF licenses this file
+ ~~ to you 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: For help with the syntax of this file, see:
+ ~~ http://maven.apache.org/doxia/references/apt-format.html
+
+Invoker Properties
+ 
+  The various parameters in the plugin configuration provide a means to globally configure the goals, profiles etc.
+  used to run a Maven build on the projects. However, for certain projects you might want to specify different settings.
+  To avoid the hassle of multiple plugin executions, you can simply use a file named <<<invoker.properties>>> to
+  control the build settings on a per project basis. The exact name of this properties file is configurable but it needs
+  to reside in the base directory of the respective project as shown below:
+
+-------------------
+./
++- src/
+   +- it/
+      +- test-project/
+         +- pom.xml
+         +- invoker.properties
+         +- src/
+-------------------
+
+  There are only a few keys supported in this file and their names typically match the corresponding parameters in the
+  plugin configuration. The snippet below provides a complete overview of supported properties:
+
++----
+# A comma or space separated list of goals/phases to execute, may
+# specify an empty list to execute the default goal of the project
+invoker.goals=clean install
+
+# Optionally, a list of goals to run during further invocations of Maven
+invoker.goals.2=\${project.groupId}:\${project.artifactId}:\${project.version}:run
+
+# A comma or space separated list of profiles to activate
+invoker.profiles=its,jdk15
+
+# The value for the environment variable MAVEN_OPTS
+invoker.mavenOpts=-Dfile.encoding=UTF-16 -Xms32m -Xmx256m
+
+# Possible values are "fail-fast" (default), "fail-at-end" and "fail-never"
+invoker.failureBehavior=fail-never
+
+# The expected result of the build, possible values are "success" (default) and "failure"
+invoker.buildResult=failure
+
+# A boolean value controlling the -N flag, defaults to "false"
+invoker.nonRecursive=false
++----
+
+  The comments given in the example should be rather self-explanatory. Looking closely, you can also notice that the
+  syntax <<<$\{expression\}>>> can be used to filter the property values. What deserves some more description is the
+  possibility to perform several Maven builds on the same project. By default, the Invoker Plugin will perform the
+  following steps for each project:
+
+  * Run the pre build hook script if existent
+
+  * Invoke Maven in the project directory
+
+  * Run the post build hook script if existent
+
+  []
+
+  Since plugin version 1.3, you can append a one-based index to the invoker properties in order to enable/configure
+  further invocations of Maven. More precisely, <<<invoker.goals.1>>> specifies the goals for the first build,
+  <<<invoker.goals.2>>> lists the goals for the second build and so on. These builds will be performed one after the
+  other:
+
+  * Run the pre build hook script if existent
+
+  * Invoke Maven in the project directory
+
+  * Invoke Maven in the project directory
+
+  * ...
+
+  * Invoke Maven in the project directory
+
+  * Run the post build hook script if existent
+
+  []
+
+  All the properties can be indexed this way, e.g. <<<invoker.profiles.3>>> would specify the profiles to use for the
+  third invocation. If the property <<<invoker.profiles.3>>> was not defined, the plugin would query the property
+  <<<invoker.profiles>>> as a fallback to determine the profiles for the third build. This build loop ends after
+  invocation <i> if the property <<<invoker.goals.>>><i+1> is undefined.

Propchange: maven/plugins/trunk/maven-invoker-plugin/src/site/apt/examples/invoker-properties.apt.vm
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: maven/plugins/trunk/maven-invoker-plugin/src/site/apt/examples/invoker-properties.apt.vm
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Modified: maven/plugins/trunk/maven-invoker-plugin/src/site/apt/index.apt
URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-invoker-plugin/src/site/apt/index.apt?rev=684144&r1=684143&r2=684144&view=diff
==============================================================================
--- maven/plugins/trunk/maven-invoker-plugin/src/site/apt/index.apt (original)
+++ maven/plugins/trunk/maven-invoker-plugin/src/site/apt/index.apt Fri Aug  8 16:40:17 2008
@@ -50,15 +50,17 @@
 * Examples
 
   The following example configurations are available:
-  
+
   * {{{examples/clone-projects.html}Clone projects}} to a new directory before running.
 
   * {{{examples/install-artifacts.html}Install}} projects artifacts to a local repository before running.
-  
+
   * {{{examples/post-build-script.html}Run a BeanShell or Groovy script}} to verify project output.
-  
+
   * {{{examples/fast-use.html}Fast Invoker Plugin configuration}} to accelerate test execution.
-  
+
   * {{{examples/access-test-classes.html}Access test classes}} to share code between IT scripts.
-  
+
+  * {{{examples/invoker-properties.html}Using Invoker Properties}} to configure goals, profiles etc. for individual projects.
+
   []

Modified: maven/plugins/trunk/maven-invoker-plugin/src/site/site.xml
URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-invoker-plugin/src/site/site.xml?rev=684144&r1=684143&r2=684144&view=diff
==============================================================================
--- maven/plugins/trunk/maven-invoker-plugin/src/site/site.xml (original)
+++ maven/plugins/trunk/maven-invoker-plugin/src/site/site.xml Fri Aug  8 16:40:17 2008
@@ -34,6 +34,7 @@
       <item name="Cloning Projects" href="examples/clone-projects.html"/>
       <item name="Fast Build Configuration" href="examples/fast-use.html"/>
       <item name="Installing Artifacts" href="examples/install-artifacts.html"/>
+      <item name="Invoker Properties" href="examples/invoker-properties.html"/>
       <item name="Using a Post Build Script" href="examples/post-build-script.html"/>
     </menu>
     

Modified: maven/plugins/trunk/maven-invoker-plugin/src/test/java/org/apache/maven/plugin/invoker/InvokerMojoTest.java
URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-invoker-plugin/src/test/java/org/apache/maven/plugin/invoker/InvokerMojoTest.java?rev=684144&r1=684143&r2=684144&view=diff
==============================================================================
--- maven/plugins/trunk/maven-invoker-plugin/src/test/java/org/apache/maven/plugin/invoker/InvokerMojoTest.java (original)
+++ maven/plugins/trunk/maven-invoker-plugin/src/test/java/org/apache/maven/plugin/invoker/InvokerMojoTest.java Fri Aug  8 16:40:17 2008
@@ -24,6 +24,7 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.Properties;
 
 import org.apache.maven.plugin.testing.AbstractMojoTestCase;
 import org.apache.maven.plugin.testing.stubs.MavenProjectStub;
@@ -205,4 +206,18 @@
         assertTrue( new File( cloneProjectsTo, "no-pom/build.log" ).isFile() );
     }
 
+    public void testGetInvokerProperty()
+    {
+        Properties props = new Properties();
+
+        assertNull( InvokerMojo.getInvokerProperty( props, "undefined-key", 0 ) );
+
+        props.setProperty( "key", "value" );
+        assertEquals( "value", InvokerMojo.getInvokerProperty( props, "key", 1 ) );
+
+        props.setProperty( "key.1", "another-value" );
+        assertEquals( "another-value", InvokerMojo.getInvokerProperty( props, "key", 1 ) );
+        assertEquals( "value", InvokerMojo.getInvokerProperty( props, "key", 2 ) );
+    }
+
 }