Coverage Report - org.apache.maven.plugin.invoker.InvokerMojo
 
Classes in this File Line Coverage Branch Coverage Complexity
InvokerMojo
64%
276/429
53%
104/196
7,3
 
 1  
 package org.apache.maven.plugin.invoker;
 2  
 
 3  
 /*
 4  
  * Licensed to the Apache Software Foundation (ASF) under one
 5  
  * or more contributor license agreements.  See the NOTICE file
 6  
  * distributed with this work for additional information
 7  
  * regarding copyright ownership.  The ASF licenses this file
 8  
  * to you under the Apache License, Version 2.0 (the
 9  
  * "License"); you may not use this file except in compliance
 10  
  * with the License.  You may obtain a copy of the License at
 11  
  *
 12  
  *  http://www.apache.org/licenses/LICENSE-2.0
 13  
  *
 14  
  * Unless required by applicable law or agreed to in writing,
 15  
  * software distributed under the License is distributed on an
 16  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 17  
  * KIND, either express or implied.  See the License for the
 18  
  * specific language governing permissions and limitations
 19  
  * under the License.
 20  
  */
 21  
 
 22  
 import java.io.BufferedReader;
 23  
 import java.io.File;
 24  
 import java.io.FileInputStream;
 25  
 import java.io.FileNotFoundException;
 26  
 import java.io.IOException;
 27  
 import java.io.InputStream;
 28  
 import java.io.PrintStream;
 29  
 import java.io.Reader;
 30  
 import java.io.Writer;
 31  
 import java.util.ArrayList;
 32  
 import java.util.Arrays;
 33  
 import java.util.Collections;
 34  
 import java.util.Iterator;
 35  
 import java.util.List;
 36  
 import java.util.Map;
 37  
 import java.util.Properties;
 38  
 import java.util.StringTokenizer;
 39  
 import java.util.TreeSet;
 40  
 
 41  
 import org.apache.maven.plugin.AbstractMojo;
 42  
 import org.apache.maven.plugin.MojoExecutionException;
 43  
 import org.apache.maven.plugin.MojoFailureException;
 44  
 import org.apache.maven.project.MavenProject;
 45  
 import org.apache.maven.settings.Settings;
 46  
 import org.apache.maven.shared.invoker.CommandLineConfigurationException;
 47  
 import org.apache.maven.shared.invoker.DefaultInvocationRequest;
 48  
 import org.apache.maven.shared.invoker.InvocationRequest;
 49  
 import org.apache.maven.shared.invoker.InvocationResult;
 50  
 import org.apache.maven.shared.invoker.Invoker;
 51  
 import org.apache.maven.shared.invoker.MavenCommandLineBuilder;
 52  
 import org.apache.maven.shared.invoker.MavenInvocationException;
 53  
 import org.apache.maven.shared.model.fileset.FileSet;
 54  
 import org.apache.maven.shared.model.fileset.util.FileSetManager;
 55  
 import org.codehaus.plexus.util.DirectoryScanner;
 56  
 import org.codehaus.plexus.util.FileUtils;
 57  
 import org.codehaus.plexus.util.IOUtil;
 58  
 import org.codehaus.plexus.util.InterpolationFilterReader;
 59  
 import org.codehaus.plexus.util.ReaderFactory;
 60  
 import org.codehaus.plexus.util.StringUtils;
 61  
 import org.codehaus.plexus.util.WriterFactory;
 62  
 import org.codehaus.plexus.util.cli.CommandLineException;
 63  
 import org.codehaus.plexus.interpolation.InterpolationException;
 64  
 import org.codehaus.plexus.interpolation.Interpolator;
 65  
 import org.codehaus.plexus.interpolation.MapBasedValueSource;
 66  
 import org.codehaus.plexus.interpolation.RegexBasedInterpolator;
 67  
 
 68  
 import bsh.EvalError;
 69  
 import bsh.Interpreter;
 70  
 
 71  
 /**
 72  
  * Searches for integration test Maven projects, and executes each, collecting a log in the project directory, and
 73  
  * outputting the results to the command line.
 74  
  *
 75  
  * @goal run
 76  
  * @phase integration-test
 77  
  * @requiresDependencyResolution test
 78  
  * @since 1.0
 79  
  *
 80  
  * @author <a href="mailto:kenney@apache.org">Kenney Westerhof</a>
 81  
  * @author <a href="mailto:jdcasey@apache.org">John Casey</a>
 82  
  * @version $Id: InvokerMojo.java 682848 2008-08-05 18:24:07Z bentmann $
 83  
  */
 84  11
 public class InvokerMojo
 85  
     extends AbstractMojo
 86  
 {
 87  
 
 88  
     /**
 89  
      * Flag used to suppress certain invocations. This is useful in tailoring the
 90  
      * build using profiles.
 91  
      *
 92  
      * @parameter default-value="false"
 93  
      * @since 1.1
 94  
      */
 95  
     private boolean skipInvocation;
 96  
 
 97  
     /**
 98  
      * Flag used to suppress the summary output notifying of successes and failures. If set to <code>true</code>,
 99  
      * the only indication of the build's success or failure will be the effect it has on the main
 100  
      * build (if it fails, the main build should fail as well). If <code>streamLogs</code> is enabled, the sub-build
 101  
      * summary will also provide an indication.
 102  
      *
 103  
      * @parameter default-value="false"
 104  
      */
 105  
     private boolean suppressSummaries;
 106  
 
 107  
     /**
 108  
      * Flag used to determine whether the build logs should be output to the normal mojo log.
 109  
      *
 110  
      * @parameter expression="${invoker.streamLogs}" default-value="false"
 111  
      */
 112  
     private boolean streamLogs;
 113  
 
 114  
     /**
 115  
      * The local repository for caching artifacts.
 116  
      *
 117  
      * @parameter expression="${invoker.localRepositoryPath}"
 118  
      */
 119  
     private File localRepositoryPath;
 120  
 
 121  
     /**
 122  
      * Directory to search for integration tests.
 123  
      *
 124  
      * @parameter expression="${invoker.projectsDirectory}" default-value="${basedir}/src/projects/"
 125  
      */
 126  
     private File projectsDirectory;
 127  
 
 128  
     /**
 129  
      * Directory to which projects should be cloned prior to execution. If not specified, each integration test will be
 130  
      * run in the directory in which the corresponding IT POM was found. In this case, you most likely want to configure
 131  
      * your SCM to ignore <code>target</code> and <code>build.log</code> in the test's base directory.
 132  
      * 
 133  
      * @parameter
 134  
      * @since 1.1
 135  
      */
 136  
     private File cloneProjectsTo;
 137  
 
 138  
     /**
 139  
      * Some files are normally excluded when copying the IT projects from the directory specified by the parameter
 140  
      * projectsDirectory to the directory given by cloneProjectsTo (e.g. <code>.svn</code>, <code>CVS</code>,
 141  
      * <code>*~</code>, etc). Setting this parameter to <code>true</code> will cause all files to be copied to the
 142  
      * cloneProjectsTo directory.
 143  
      * 
 144  
      * @parameter default-value="false"
 145  
      * @since 1.2
 146  
      */
 147  
     private boolean cloneAllFiles;
 148  
 
 149  
     /**
 150  
      * A single POM to build, skipping any scanning parameters and behavior.
 151  
      *
 152  
      * @parameter expression="${invoker.pom}"
 153  
      */
 154  
     private File pom;
 155  
 
 156  
     /**
 157  
      * Includes for searching the integration test directory. This parameter is meant to be set from the POM.
 158  
      * If this parameter is not set, the plugin will search for all <code>pom.xml</code> files one directory below
 159  
      * {@link #projectsDirectory} (<code>*&#47;pom.xml</code>).
 160  
      *
 161  
      * @parameter
 162  
      */
 163  11
     private List pomIncludes = Collections.singletonList( "*/pom.xml" );
 164  
 
 165  
     /**
 166  
      * Excludes for searching the integration test directory. This parameter is meant to be set from the POM. By
 167  
      * default, no POM files are excluded.
 168  
      * 
 169  
      * @parameter
 170  
      */
 171  11
     private List pomExcludes = Collections.EMPTY_LIST;
 172  
 
 173  
     /**
 174  
      * The list of goals to execute on each project. Default value is: <code>package</code>.
 175  
      *
 176  
      * @parameter
 177  
      */
 178  11
     private List goals = Collections.singletonList( "package" );
 179  
 
 180  
     /**
 181  
      * The name of the project-specific file that contains the enumeration of goals to execute for that test.
 182  
      * 
 183  
      * @parameter expression="${invoker.goalsFile}" default-value="goals.txt"
 184  
      * @deprecated As of version 1.2 the properties file specified by the parameter invokerPropertiesFile should be used
 185  
      *             instead.
 186  
      */
 187  
     private String goalsFile;
 188  
 
 189  
     /**
 190  
      * @component
 191  
      */
 192  
     private Invoker invoker;
 193  
 
 194  
     /**
 195  
      * Relative path of a pre-build hook BeanShell script to run prior to executing the build.
 196  
      *
 197  
      * @parameter expression="${invoker.preBuildHookScript}" default-value="prebuild.bsh"
 198  
      */
 199  
     private String preBuildHookScript;
 200  
 
 201  
     /**
 202  
      * Relative path of a cleanup/verification BeanShell script to run after executing the build.
 203  
      *
 204  
      * @parameter expression="${invoker.postBuildHookScript}" default-value="postbuild.bsh"
 205  
      */
 206  
     private String postBuildHookScript;
 207  
 
 208  
     /**
 209  
      * Location of a properties file that defines CLI properties for the test.
 210  
      *
 211  
      * @parameter expression="${invoker.testPropertiesFile}" default-value="test.properties"
 212  
      */
 213  
     private String testPropertiesFile;
 214  
 
 215  
     /**
 216  
      * Common set of test properties to pass in on each IT's command line, via -D parameters.
 217  
      *
 218  
      * @parameter
 219  
      * @deprecated Use properties parameter instead.
 220  
      */
 221  
     private Properties testProperties;
 222  
 
 223  
     /**
 224  
      * Common set of properties to pass in on each project's command line, via -D parameters.
 225  
      *
 226  
      * @parameter
 227  
      * @since 1.1
 228  
      */
 229  
     private Map properties;
 230  
 
 231  
     /**
 232  
      * Whether to show errors in the build output.
 233  
      *
 234  
      * @parameter expression="${invoker.showErrors}" default-value="false"
 235  
      */
 236  
     private boolean showErrors;
 237  
 
 238  
     /**
 239  
      * Whether to show debug statements in the build output.
 240  
      *
 241  
      * @parameter expression="${invoker.debug}" default-value="false"
 242  
      */
 243  
     private boolean debug;
 244  
 
 245  
     /**
 246  
      * Suppress logging to the <code>build.log</code> file.
 247  
      *
 248  
      * @parameter expression="${invoker.noLog}" default-value="false"
 249  
      */
 250  
     private boolean noLog;
 251  
 
 252  
     /**
 253  
      * List of profile identifiers to explicitly trigger in the build.
 254  
      * 
 255  
      * @parameter
 256  
      * @since 1.1
 257  
      */
 258  
     private List profiles;
 259  
 
 260  
     /**
 261  
      * List of properties which will be used to interpolate goal files.
 262  
      *
 263  
      * @parameter
 264  
      * @since 1.1
 265  
      */
 266  
     private Properties interpolationsProperties;
 267  
 
 268  
     /**
 269  
      * The Maven Project Object
 270  
      *
 271  
      * @parameter expression="${project}"
 272  
      * @required
 273  
      * @readonly
 274  
      * @since 1.1
 275  
      */
 276  
     private MavenProject project;
 277  
 
 278  
     /**
 279  
      * Specify this parameter to run individual tests by file name, overriding the <code>pomIncludes</code>
 280  
      * and <code>pomExcludes</code> parameters.  Each pattern you specify here will be used to create an 
 281  
      * include pattern formatted like <code>${projectsDirectory}/${invoker.test}</code>, 
 282  
      * so you can just type "-Dinvoker.test=MyTest" to run a single it in ${projectsDirectory}/${invoker.test}".  
 283  
      * 
 284  
      * @parameter expression="${invoker.test}"
 285  
      * @since 1.1
 286  
      */
 287  
     private String invokerTest;
 288  
 
 289  
     /**
 290  
      * The name of the project-specific file that contains the enumeration of profiles to use for that test. <b>If the
 291  
      * file exists and empty no profiles will be used even if the profiles is set</b>
 292  
      * 
 293  
      * @parameter expression="${invoker.profilesFile}" default-value="profiles.txt"
 294  
      * @since 1.1
 295  
      * @deprecated As of version 1.2 the properties file specified by the parameter invokerPropertiesFile should be used
 296  
      *             instead.
 297  
      */
 298  
     private String profilesFile;
 299  
 
 300  
     /**
 301  
      * Path to an alternate <code>settings.xml</code> to use for Maven invocation with all ITs.
 302  
      * 
 303  
      * @parameter expression="${invoker.settingsFile}"
 304  
      * @since 1.2
 305  
      */
 306  
     private File settingsFile;
 307  
 
 308  
     /**
 309  
      * The <code>MAVEN_OPTS</code> environment variable to use when invoking Maven. This value can be overridden for
 310  
      * individual integration tests by using {@link #invokerPropertiesFile}.
 311  
      * 
 312  
      * @parameter expression="${invoker.mavenOpts}"
 313  
      * @since 1.2
 314  
      */
 315  
     private String mavenOpts;
 316  
 
 317  
     /**
 318  
      * The file encoding for the pre-/post-build scripts and the list files for goals and profiles.
 319  
      * 
 320  
      * @parameter expression="${encoding}" default-value="${project.build.sourceEncoding}"
 321  
      * @since 1.2
 322  
      */
 323  
     private String encoding;
 324  
     
 325  
     /**
 326  
      * The current user system settings for use in Maven.
 327  
      *
 328  
      * @parameter expression="${settings}"
 329  
      * @required
 330  
      * @readonly
 331  
      * @since 1.2
 332  
      */
 333  
     private Settings settings;    
 334  
 
 335  
     /**
 336  
      * A flag whether the test class path of the project under test should be included in the class path of the
 337  
      * pre-/post-build scripts. If set to <code>false</code>, the class path of script interpreter consists only of
 338  
      * the <a href="dependencies.html">runtime dependencies</a> of the Maven Invoker Plugin. If set the
 339  
      * <code>true</code>, the project's test class path will be prepended to the interpreter class path. Among
 340  
      * others, this feature allows the scripts to access utility classes from the test sources of your project.
 341  
      * 
 342  
      * @parameter expression="${invoker.addTestClassPath}" default-value="false"
 343  
      * @since 1.2
 344  
      */
 345  
     private boolean addTestClassPath;
 346  
 
 347  
     /**
 348  
      * The name of an optional test-specific file that contains properties used to configure the invocation of an
 349  
      * integration test. This properties file may be used to specify settings for an individual test invocation. Any
 350  
      * property present in the file will override the corresponding setting from the plugin configuration. The values of
 351  
      * the properties are filtered and may use expressions like <code>${project.version}</code> to reference project
 352  
      * properties or values from the parameter {@link #interpolationsProperties}. The snippet below describes the
 353  
      * supported properties:
 354  
      * 
 355  
      * <pre>
 356  
      * # A comma or space separated list of goals/phases to execute, may
 357  
      * # specify an empty list to execute the default goal of the IT project
 358  
      * invoker.goals=clean package site
 359  
      * 
 360  
      * # A comma or space separated list of profiles to activate
 361  
      * invoker.profiles=its,jdk15
 362  
      * 
 363  
      * # The value for the environment variable MAVEN_OPTS
 364  
      * invoker.mavenOpts=-Dfile.encoding=UTF-16 -Xms32m -Xmx256m
 365  
      * 
 366  
      * # Possible values are &quot;fail-fast&quot; (default), &quot;fail-at-end&quot; and &quot;fail-never&quot;
 367  
      * invoker.failureBehavior=fail-never
 368  
      * 
 369  
      * # The expected result of the build, possible values are &quot;success&quot; (default) and &quot;failure&quot;
 370  
      * invoker.buildResult=failure
 371  
      * 
 372  
      * # A boolean value controlling the -N flag, defaults to &quot;false&quot;
 373  
      * invoker.nonRecursive=false
 374  
      * </pre>
 375  
      * 
 376  
      * @parameter expression="${invoker.invokerPropertiesFile}" default-value="invoker.properties"
 377  
      * @since 1.2
 378  
      */
 379  
     private String invokerPropertiesFile;
 380  
 
 381  
 
 382  
     public void execute()
 383  
         throws MojoExecutionException, MojoFailureException
 384  
     {
 385  2
         if ( skipInvocation )
 386  
         {
 387  0
             getLog().info( "Skipping invocation per configuration."
 388  
                 + " If this is incorrect, ensure the skipInvocation parameter is not set to true." );
 389  0
             return;
 390  
         }
 391  
 
 392  
         String[] includedPoms;
 393  2
         if ( pom != null )
 394  
         {
 395  
             try
 396  
             {
 397  0
                 projectsDirectory = pom.getCanonicalFile().getParentFile();
 398  
             }
 399  0
             catch ( IOException e )
 400  
             {
 401  0
                 throw new MojoExecutionException( "Failed to discover projectsDirectory from pom File parameter."
 402  
                     + " Reason: " + e.getMessage(), e );
 403  0
             }
 404  
 
 405  0
             includedPoms = new String[]{ pom.getName() };
 406  
         }
 407  
         else
 408  
         {
 409  
             try
 410  
             {
 411  2
                 includedPoms = getPoms();
 412  
             }
 413  0
             catch ( final IOException e )
 414  
             {
 415  0
                 throw new MojoExecutionException( "Error retrieving POM list from includes, excludes, "
 416  
                                 + "and projects directory. Reason: " + e.getMessage(), e );
 417  2
             }
 418  
         }
 419  
 
 420  
 
 421  2
         if ( ( includedPoms == null ) || ( includedPoms.length < 1 ) )
 422  
         {
 423  0
             getLog().info( "No test-projects were selected for execution." );
 424  0
             return;
 425  
         }
 426  
 
 427  2
         if ( StringUtils.isEmpty( encoding ) )
 428  
         {
 429  2
             getLog().warn(
 430  
                            "File encoding has not been set, using platform encoding " + ReaderFactory.FILE_ENCODING
 431  
                                + ", i.e. build is platform dependent!" );
 432  
         }
 433  
 
 434  2
         File projectsDir = projectsDirectory;
 435  
 
 436  2
         if ( cloneProjectsTo != null )
 437  
         {
 438  2
             cloneProjectsTo.mkdirs();
 439  
 
 440  
             try
 441  
             {
 442  2
                 cloneProjects( includedPoms );
 443  
             }
 444  0
             catch ( IOException e )
 445  
             {
 446  0
                 throw new MojoExecutionException( "Failed to clone projects from: " + projectsDirectory + " to: "
 447  
                     + cloneProjectsTo + ". Reason: " + e.getMessage(), e );
 448  2
             }
 449  
 
 450  2
             projectsDir = cloneProjectsTo;
 451  
         }
 452  
 
 453  2
         final List failures = new ArrayList();
 454  
 
 455  6
         for ( int i = 0; i < includedPoms.length; i++ )
 456  
         {
 457  4
             final String pom = includedPoms[i];
 458  
 
 459  4
             runBuild( projectsDir, pom, failures );
 460  
         }
 461  
 
 462  
 
 463  2
         if ( !suppressSummaries )
 464  
         {
 465  2
             final StringBuffer summary = new StringBuffer();
 466  2
             summary.append( "\n\n" );
 467  2
             summary.append( "---------------------------------------\n" );
 468  2
             summary.append( "Execution Summary:\n" );
 469  2
             summary.append( "Builds Passing: " ).append( includedPoms.length - failures.size() ).append( "\n" );
 470  2
             summary.append( "Builds Failing: " ).append( failures.size() ).append( "\n" );
 471  2
             summary.append( "---------------------------------------\n" );
 472  
 
 473  2
             if ( !failures.isEmpty() )
 474  
             {
 475  0
                 summary.append( "\nThe following builds failed:\n" );
 476  
 
 477  0
                 for ( final Iterator it = failures.iterator(); it.hasNext(); )
 478  
                 {
 479  0
                     final String pom = ( String ) it.next();
 480  0
                     summary.append( "\n*  " ).append( pom );
 481  
                 }
 482  
 
 483  0
                 summary.append( "\n" );
 484  
             }
 485  
 
 486  2
             getLog().info( summary.toString() );
 487  
         }
 488  
 
 489  2
         if ( !failures.isEmpty() )
 490  
         {
 491  0
             String message = failures.size() + " builds failed.";
 492  
 
 493  0
             throw new MojoFailureException( this, message, message );
 494  
         }
 495  2
     }
 496  
 
 497  
     /**
 498  
      * Creates a new reader for the specified file, using the plugin's {@link #encoding} parameter.
 499  
      * 
 500  
      * @param file The file to create a reader for, must not be <code>null</code>.
 501  
      * @return The reader for the file, never <code>null</code>.
 502  
      * @throws IOException If the specified file was not found or the configured encoding is not supported.
 503  
      */
 504  
     private Reader newReader( File file )
 505  
         throws IOException
 506  
     {
 507  7
         if ( StringUtils.isNotEmpty( encoding ) )
 508  
         {
 509  0
             return ReaderFactory.newReader( file, encoding );
 510  
         }
 511  
         else
 512  
         {
 513  7
             return ReaderFactory.newPlatformReader( file );
 514  
         }
 515  
     }
 516  
 
 517  
     private void cloneProjects( String[] includedPoms )
 518  
         throws IOException
 519  
     {
 520  2
         List clonedSubpaths = new ArrayList();
 521  
 
 522  6
         for ( int i = 0; i < includedPoms.length; i++ )
 523  
         {
 524  4
             String subpath = includedPoms[i];
 525  4
             int lastSep = subpath.lastIndexOf( File.separator );
 526  
 
 527  4
             if ( lastSep > -1 )
 528  
             {
 529  3
                 subpath = subpath.substring( 0, lastSep );
 530  
             }
 531  
             else
 532  
             {
 533  1
                 subpath = ".";
 534  
             }
 535  
 
 536  
             // avoid copying subdirs that are already cloned.
 537  4
             if ( !alreadyCloned( subpath, clonedSubpaths ) )
 538  
             {
 539  
                 // avoid creating new files that point to dir/.
 540  3
                 if ( ".".equals( subpath ) )
 541  
                 {
 542  1
                     String cloneSubdir = normalizePath( cloneProjectsTo, projectsDirectory.getCanonicalPath() );
 543  
 
 544  
                     // avoid infinite recursion if the cloneTo path is a subdirectory.
 545  1
                     if ( cloneSubdir != null )
 546  
                     {
 547  0
                         File temp = File.createTempFile( "pre-invocation-clone.", "" );
 548  0
                         temp.delete();
 549  0
                         temp.mkdirs();
 550  
 
 551  0
                         copyDirectoryStructure( projectsDirectory, temp );
 552  
 
 553  0
                         FileUtils.deleteDirectory( new File( temp, cloneSubdir ) );
 554  
 
 555  0
                         copyDirectoryStructure( temp, cloneProjectsTo );
 556  
                     }
 557  
                     else
 558  
                     {
 559  1
                         copyDirectoryStructure( projectsDirectory, cloneProjectsTo );
 560  
                     }
 561  
                 }
 562  
                 else
 563  
                 {
 564  2
                     copyDirectoryStructure( new File( projectsDirectory, subpath ), new File( cloneProjectsTo,
 565  
                                                                                               subpath ) );
 566  
                 }
 567  
 
 568  3
                 clonedSubpaths.add( subpath );
 569  
             }
 570  
         }
 571  2
     }
 572  
     
 573  
     /**
 574  
      * Copied a directory structure with deafault exclusions (.svn, CVS, etc)
 575  
      * 
 576  
      * @param sourceDir
 577  
      * @param destDir
 578  
      * @throws IOException
 579  
      */
 580  
     private void copyDirectoryStructure( File sourceDir, File destDir ) throws IOException
 581  
     {
 582  3
         DirectoryScanner scanner = new DirectoryScanner();
 583  3
         scanner.setBasedir( sourceDir );
 584  3
         if ( ! cloneAllFiles )
 585  
         {
 586  3
             scanner.addDefaultExcludes();
 587  
         }
 588  3
         scanner.scan();
 589  
         
 590  3
         String [] includedFiles = scanner.getIncludedFiles();
 591  10
         for ( int i = 0; i < includedFiles.length; ++i )
 592  
         {
 593  7
             File sourceFile = new File( sourceDir, includedFiles[ i ] );
 594  7
             File destFile = new File( destDir, includedFiles[ i ] );
 595  7
             FileUtils.copyFile( sourceFile, destFile );
 596  
         }
 597  3
     }
 598  
 
 599  
     static boolean alreadyCloned( String subpath, List clonedSubpaths )
 600  
     {
 601  8
         for ( Iterator iter = clonedSubpaths.iterator(); iter.hasNext(); )
 602  
         {
 603  6
             String path = (String) iter.next();
 604  
 
 605  6
             if ( ".".equals( path ) || subpath.equals( path ) || subpath.startsWith( path + File.separator ) )
 606  
             {
 607  3
                 return true;
 608  
             }
 609  
         }
 610  
 
 611  5
         return false;
 612  
     }
 613  
 
 614  
     private void runBuild( final File projectsDir, final String pom, final List failures )
 615  
         throws MojoExecutionException
 616  
     {
 617  
 
 618  4
         File pomFile = new File( projectsDir, pom );
 619  4
         final File basedir = pomFile.getParentFile();
 620  4
         File interpolatedPomFile = buildInterpolatedFile( pomFile, basedir, "interpolated-pom.xml" );
 621  4
         FileLogger logger = null;
 622  
         try
 623  
         {
 624  4
             getLog().info( "Building: " + pom );
 625  
 
 626  4
             final File outputLog = new File( basedir, "build.log" );
 627  
 
 628  4
             final Properties invokerProperties = getInvokerProperties( basedir );
 629  4
             if ( getLog().isDebugEnabled() && !invokerProperties.isEmpty() )
 630  
             {
 631  0
                 getLog().debug( "Using invoker properties:" );
 632  0
                 for ( Iterator it = new TreeSet( invokerProperties.keySet() ).iterator(); it.hasNext(); )
 633  
                 {
 634  0
                     String key = (String) it.next();
 635  0
                     String value = invokerProperties.getProperty( key );
 636  0
                     getLog().debug( "  " + key + " = " + value );
 637  
                 }
 638  
             }
 639  
 
 640  4
             if ( !noLog )
 641  
             {
 642  4
                 outputLog.getParentFile().mkdirs();
 643  
 
 644  
                 try
 645  
                 {
 646  4
                     if ( streamLogs )
 647  
                     {
 648  0
                         logger = new FileLogger( outputLog, getLog() );
 649  
                     }
 650  
                     else
 651  
                     {
 652  4
                         logger = new FileLogger( outputLog );
 653  
                     }
 654  
 
 655  4
                     getLog().debug( "build log initialized in: " + outputLog );
 656  
                 }
 657  0
                 catch ( final IOException e )
 658  
                 {
 659  0
                     getLog().debug( "Error initializing build logfile in: " + outputLog, e );
 660  0
                     getLog().info( "...FAILED[could not initialize logfile in: " + outputLog + "]" );
 661  
 
 662  0
                     failures.add( pom );
 663  
 
 664  
                     return;
 665  4
                 }
 666  
             }
 667  
 
 668  4
             if ( !prebuild( basedir, interpolatedPomFile, failures, logger ) )
 669  
             {
 670  0
                 getLog().info( "...FAILED[pre-build script returned false]" );
 671  
 
 672  0
                 failures.add( pom );
 673  
 
 674  
                 return;
 675  
             }
 676  
 
 677  4
             final InvocationRequest request = new DefaultInvocationRequest();
 678  
 
 679  4
             final List invocationGoals = getGoals( basedir );
 680  
 
 681  4
             if ( ( invocationGoals.size() == 1 ) && "_default".equals( invocationGoals.get( 0 ) ) )
 682  
             {
 683  0
                 getLog().debug( "Executing default goal for project in: " + pom );
 684  
             }
 685  
             else
 686  
             {
 687  4
                 getLog().debug( "Executing goals: " + invocationGoals + " for project in: " + pom );
 688  
 
 689  4
                 request.setGoals( invocationGoals );
 690  
             }
 691  
 
 692  
             try
 693  
             {
 694  4
                 Properties collectedTestProperties = new Properties();
 695  
 
 696  4
                 if ( testProperties != null )
 697  
                 {
 698  0
                     collectedTestProperties.putAll( testProperties );
 699  
                 }
 700  
 
 701  4
                 if ( properties != null )
 702  
                 {
 703  0
                     collectedTestProperties.putAll( properties );
 704  
                 }
 705  
 
 706  4
                 final Properties loadedProperties = loadTestProperties( basedir );
 707  
 
 708  4
                 if ( loadedProperties != null )
 709  
                 {
 710  4
                     collectedTestProperties.putAll( loadedProperties );
 711  
                 }
 712  
 
 713  4
                 request.setProperties( collectedTestProperties );
 714  
             }
 715  0
             catch ( final IOException e )
 716  
             {
 717  0
                 getLog().debug( "Error reading test-properties file in: " + testPropertiesFile, e );
 718  0
                 getLog().info( "...FAILED[error reading test properties in: " + testPropertiesFile + "]" );
 719  
 
 720  0
                 failures.add( pom );
 721  
 
 722  
                 return;
 723  4
             }
 724  
 
 725  4
             if ( localRepositoryPath != null )
 726  
             {
 727  0
                 File localRepoDir = localRepositoryPath;
 728  
 
 729  0
                 getLog().debug( "Using local repository: " + localRepoDir );
 730  
 
 731  0
                 if ( ! localRepositoryPath.exists() )
 732  
                 {
 733  0
                     localRepositoryPath.mkdirs();
 734  
                 }
 735  
                 
 736  0
                 request.setLocalRepositoryDirectory( localRepoDir );
 737  
             }
 738  
 
 739  4
             request.setInteractive( false );
 740  
 
 741  4
             request.setShowErrors( showErrors );
 742  
 
 743  4
             request.setDebug( debug );
 744  
 
 745  4
             request.setBaseDirectory( basedir );
 746  
 
 747  4
             if ( !noLog )
 748  
             {
 749  4
                 request.setErrorHandler( logger );
 750  
 
 751  4
                 request.setOutputHandler( logger );
 752  
             }
 753  
 
 754  4
             request.setPomFile( interpolatedPomFile );
 755  
 
 756  4
             request.setProfiles( getProfiles( basedir ) );
 757  
 
 758  4
             if ( settingsFile != null )
 759  
             {
 760  0
                 buildInterpolatedFile( settingsFile, settingsFile.getParentFile(), settingsFile.getName()
 761  
                     + ".interpolated" );
 762  0
                 request.setUserSettingsFile( new File( settingsFile.getParentFile(), settingsFile.getName()
 763  
                     + ".interpolated" ) );
 764  
             }
 765  
 
 766  4
             request.setMavenOpts( mavenOpts );
 767  
 
 768  4
             configureInvocation( request, invokerProperties );
 769  
 
 770  
             try
 771  
             {
 772  4
                 getLog().debug( "Using MAVEN_OPTS: " + request.getMavenOpts() );
 773  4
                 getLog().debug( "Executing: " + new MavenCommandLineBuilder().build( request ) );
 774  
             }
 775  0
             catch ( CommandLineConfigurationException e )
 776  
             {
 777  0
                 getLog().debug( "Failed to display command line: " + e.getMessage() );
 778  4
             }
 779  
 
 780  4
             InvocationResult result = null;
 781  
 
 782  
             try
 783  
             {
 784  4
                 result = invoker.execute( request );
 785  
             }
 786  0
             catch ( final MavenInvocationException e )
 787  
             {
 788  0
                 getLog().debug( "Error invoking Maven: " + e.getMessage(), e );
 789  0
                 getLog().info( "...FAILED[error invoking Maven]" );
 790  
 
 791  0
                 failures.add( pom );
 792  
 
 793  
                 return;
 794  4
             }
 795  
 
 796  4
             final CommandLineException executionException = result.getExecutionException();
 797  4
             final boolean nonZeroExit =
 798  
                 "failure".equalsIgnoreCase( invokerProperties.getProperty( "invoker.buildResult" ) );
 799  
 
 800  4
             if ( executionException != null )
 801  
             {
 802  0
                 if ( !suppressSummaries )
 803  
                 {
 804  0
                     StringBuffer buffer = new StringBuffer( 256 );
 805  0
                     buffer.append( "...FAILED. " );
 806  0
                     if ( !noLog )
 807  
                     {
 808  0
                         buffer.append( "See " ).append( outputLog.getAbsolutePath() ).append( " for details." );
 809  
                     }
 810  
                     else
 811  
                     {
 812  0
                         buffer.append( "See console output for details." );
 813  
                     }
 814  0
                     getLog().info( buffer.toString() );
 815  
                 }
 816  
 
 817  0
                 failures.add( pom );
 818  
             }
 819  4
             else if ( ( result.getExitCode() != 0 ) != nonZeroExit )
 820  
             {
 821  0
                 if ( !suppressSummaries )
 822  
                 {
 823  0
                     StringBuffer buffer = new StringBuffer( 256 );
 824  0
                     buffer.append( "...FAILED[code=" ).append( result.getExitCode() ).append( "]. " );
 825  0
                     if ( !noLog )
 826  
                     {
 827  0
                         buffer.append( "See " ).append( outputLog.getAbsolutePath() ).append( " for details." );
 828  
                     }
 829  
                     else
 830  
                     {
 831  0
                         buffer.append( "See console output for details." );
 832  
                     }
 833  0
                     getLog().info( buffer.toString() );
 834  
                 }
 835  
 
 836  0
                 failures.add( pom );
 837  
             }
 838  4
             else if ( !verify( basedir, interpolatedPomFile, failures, logger ) )
 839  
             {
 840  0
                 if ( !suppressSummaries )
 841  
                 {
 842  0
                     getLog().info( "...FAILED[verify script returned false]." );
 843  
                 }
 844  
 
 845  0
                 failures.add( pom );
 846  
             }
 847  4
             else if ( !suppressSummaries )
 848  
             {
 849  4
                 getLog().info( "...SUCCESS." );
 850  
             }
 851  
         }
 852  
         finally
 853  
         {
 854  4
             if ( logger != null )
 855  
             {
 856  4
                 logger.close();
 857  
             }
 858  
         }
 859  4
     }
 860  
 
 861  
     private Properties loadTestProperties( final File basedir )
 862  
         throws IOException
 863  
     {
 864  4
         final Properties testProps = new Properties();
 865  
 
 866  4
         if ( testPropertiesFile != null )
 867  
         {
 868  0
             final File testProperties = new File( basedir, testPropertiesFile );
 869  
 
 870  0
             if ( testProperties.exists() )
 871  
             {
 872  0
                 InputStream fin = null;
 873  
                 try
 874  
                 {
 875  0
                     fin = new FileInputStream( testProperties );
 876  
 
 877  0
                     testProps.load( fin );
 878  
                 }
 879  
                 finally
 880  
                 {
 881  0
                     IOUtil.close( fin );
 882  0
                 }
 883  
             }
 884  
         }
 885  
 
 886  4
         return testProps;
 887  
     }
 888  
 
 889  
     private boolean verify( final File basedir, final File pom, final List failures, final FileLogger logger )
 890  
     {
 891  4
         boolean result = true;
 892  
 
 893  4
         if ( postBuildHookScript != null )
 894  
         {
 895  
             try
 896  
             {
 897  1
                 result = runScript( "verification script", basedir, postBuildHookScript, logger );
 898  
             }
 899  0
             catch ( final IOException e )
 900  
             {
 901  0
                 result = false;
 902  
             }
 903  0
             catch ( final EvalError e )
 904  
             {
 905  0
                 String errorMessage = "error evaluating script " + basedir.getPath() + File.separatorChar
 906  
                     + postBuildHookScript + ", " + e.getMessage();
 907  0
                 getLog().error( errorMessage, e );
 908  0
                 result = false;
 909  1
             }
 910  
         }
 911  
 
 912  4
         return result;
 913  
     }
 914  
 
 915  
     private boolean runScript( final String scriptDescription, final File basedir, final String relativeScriptPath,
 916  
                                final FileLogger logger )
 917  
         throws IOException, EvalError
 918  
     {
 919  1
         final File script = new File( basedir, relativeScriptPath );
 920  
 
 921  1
         boolean scriptResult = false;
 922  
 
 923  1
         if ( script.exists() )
 924  
         {
 925  1
             final Interpreter engine = new Interpreter();
 926  
 
 927  1
             if ( addTestClassPath )
 928  
             {
 929  0
                 getLog().debug( "Adding test class path to BeanShell interpreter:" );
 930  
                 try
 931  
                 {
 932  0
                     List testClassPath = project.getTestClasspathElements();
 933  0
                     for ( Iterator it = testClassPath.iterator(); it.hasNext(); )
 934  
                     {
 935  0
                         String path = (String) it.next();
 936  0
                         getLog().debug( "  " + path );
 937  0
                         engine.getClassManager().addClassPath( new File( path ).toURI().toURL() );
 938  
                     }
 939  
                 }
 940  0
                 catch ( Exception e )
 941  
                 {
 942  0
                     getLog().error( "Failed to add test class path to BeanShell interpreter", e );
 943  0
                 }
 944  
             }
 945  
 
 946  1
             PrintStream origOut = System.out;
 947  1
             PrintStream origErr = System.err;
 948  
 
 949  1
             Reader reader = null;
 950  
             try
 951  
             {
 952  1
                 if ( !noLog )
 953  
                 {
 954  1
                     logger.consumeLine( "Running " + scriptDescription + " in: " + script );
 955  
 
 956  1
                     System.setErr( logger.getPrintStream() );
 957  1
                     System.setOut( logger.getPrintStream() );
 958  
 
 959  1
                     engine.setErr( logger.getPrintStream() );
 960  1
                     engine.setOut( logger.getPrintStream() );
 961  
                 }
 962  
 
 963  1
                 engine.set( "basedir", basedir );
 964  
 
 965  1
                 reader = newReader( script );
 966  
 
 967  1
                 final Object result = engine.eval( reader );
 968  
 
 969  1
                 scriptResult = Boolean.TRUE.equals( result ) || "true".equals( result );
 970  
             }
 971  
             finally
 972  
             {
 973  1
                 IOUtil.close( reader );
 974  1
                 System.setErr( origErr );
 975  1
                 System.setOut( origOut );
 976  1
             }
 977  
 
 978  1
             if ( !noLog )
 979  
             {
 980  1
                 logger.consumeLine( "Finished " + scriptDescription + " in: " + script );
 981  
             }
 982  
         }
 983  
         else
 984  
         {
 985  0
             scriptResult = true;
 986  
         }
 987  
 
 988  1
         return scriptResult;
 989  
     }
 990  
 
 991  
     private boolean prebuild( final File basedir, final File pom, final List failures, final FileLogger logger )
 992  
     {
 993  4
         boolean result = true;
 994  
 
 995  4
         if ( preBuildHookScript != null )
 996  
         {
 997  
             try
 998  
             {
 999  0
                 result = runScript( "pre-build script", basedir, preBuildHookScript, logger );
 1000  
             }
 1001  0
             catch ( final IOException e )
 1002  
             {
 1003  0
                 result = false;
 1004  
             }
 1005  0
             catch ( final EvalError e )
 1006  
             {
 1007  0
                 String errorMessage = "error evaluating script " + basedir.getPath() + File.separatorChar
 1008  
                     + postBuildHookScript + ", " + e.getMessage();
 1009  0
                 getLog().error( errorMessage, e );
 1010  0
                 result = false;
 1011  0
             }
 1012  
         }
 1013  
 
 1014  4
         return result;
 1015  
     }
 1016  
 
 1017  
     protected List getGoals( final File basedir )
 1018  
     {
 1019  10
         List invocationGoals = goals;
 1020  
 
 1021  10
         if ( goalsFile != null )
 1022  
         {
 1023  7
             final File projectGoalList = new File( basedir, goalsFile );
 1024  
 
 1025  7
             if ( projectGoalList.exists() )
 1026  
             {
 1027  4
                 final List goals = readFromFile( projectGoalList );
 1028  
 
 1029  4
                 if ( ( goals != null ) && !goals.isEmpty() )
 1030  
                 {
 1031  4
                     getLog().debug( "Using goals specified in file: " + projectGoalList );
 1032  4
                     invocationGoals = goals;
 1033  
                 }
 1034  
             }
 1035  
         }
 1036  
 
 1037  10
         return invocationGoals;
 1038  
     }
 1039  
 
 1040  
     protected String[] getPoms()
 1041  
         throws IOException
 1042  
     {
 1043  
         String[] poms;
 1044  
 
 1045  5
         if ( ( pom != null ) && pom.exists() )
 1046  
         {
 1047  0
             poms = new String[]{ pom.getAbsolutePath() };
 1048  
         }
 1049  5
         else if ( invokerTest != null )
 1050  
         {
 1051  3
             String[] testRegexes = StringUtils.split( invokerTest, "," );
 1052  3
             List /* String */includes = new ArrayList( testRegexes.length );
 1053  
 
 1054  7
             for ( int i = 0, size = testRegexes.length; i < size; i++ )
 1055  
             {
 1056  
                 // user just use -Dinvoker.test=MWAR191,MNG111 to use a directory thats the end is not pom.xml
 1057  4
                 includes.add( testRegexes[i].endsWith( "pom.xml" ) ? testRegexes[i] : testRegexes[i]
 1058  
                     + File.separatorChar + "pom.xml" );
 1059  
             }
 1060  
 
 1061  3
             final FileSet fs = new FileSet();
 1062  
 
 1063  3
             fs.setIncludes( includes );
 1064  
             //fs.setExcludes( pomExcludes );
 1065  3
             fs.setDirectory( projectsDirectory.getCanonicalPath() );
 1066  3
             fs.setFollowSymlinks( false );
 1067  3
             fs.setUseDefaultExcludes( false );
 1068  
 
 1069  3
             final FileSetManager fsm = new FileSetManager( getLog() );
 1070  
 
 1071  3
             poms = fsm.getIncludedFiles( fs );
 1072  
         }
 1073  
         else
 1074  
         {
 1075  2
             final FileSet fs = new FileSet();
 1076  
 
 1077  2
             fs.setIncludes( pomIncludes );
 1078  2
             fs.setExcludes( pomExcludes );
 1079  2
             fs.setDirectory( projectsDirectory.getCanonicalPath() );
 1080  2
             fs.setFollowSymlinks( false );
 1081  2
             fs.setUseDefaultExcludes( false );
 1082  
 
 1083  2
             final FileSetManager fsm = new FileSetManager( getLog() );
 1084  
 
 1085  2
             poms = fsm.getIncludedFiles( fs );
 1086  
         }
 1087  
 
 1088  5
         poms = normalizePomPaths( poms );
 1089  
 
 1090  5
         return poms;
 1091  
     }
 1092  
 
 1093  
     private String[] normalizePomPaths( String[] poms )
 1094  
         throws IOException
 1095  
     {
 1096  5
         String projectsDirPath = projectsDirectory.getCanonicalPath();
 1097  
 
 1098  5
         String[] results = new String[poms.length];
 1099  16
         for ( int i = 0; i < poms.length; i++ )
 1100  
         {
 1101  11
             String pomPath = poms[i];
 1102  
 
 1103  11
             File pom = new File( pomPath );
 1104  
 
 1105  11
             if ( !pom.isAbsolute() )
 1106  
             {
 1107  11
                 pom = new File( projectsDirectory, pomPath );
 1108  
             }
 1109  
 
 1110  11
             String normalizedPath = normalizePath( pom, projectsDirPath );
 1111  
 
 1112  11
             if ( normalizedPath == null )
 1113  
             {
 1114  0
                 normalizedPath = pomPath;
 1115  
             }
 1116  
 
 1117  11
             results[i] = normalizedPath;
 1118  
         }
 1119  
 
 1120  5
         return results;
 1121  
     }
 1122  
 
 1123  
     private String normalizePath( File path, String withinDirPath )
 1124  
         throws IOException
 1125  
     {
 1126  12
         String normalizedPath = path.getCanonicalPath();
 1127  
 
 1128  12
         if ( normalizedPath.startsWith( withinDirPath ) )
 1129  
         {
 1130  11
             normalizedPath = normalizedPath.substring( withinDirPath.length() );
 1131  11
             if ( normalizedPath.startsWith( File.separator ) )
 1132  
             {
 1133  11
                 normalizedPath = normalizedPath.substring( File.separator.length() );
 1134  
             }
 1135  
 
 1136  11
             return normalizedPath;
 1137  
         }
 1138  
         else
 1139  
         {
 1140  1
             return null;
 1141  
         }
 1142  
     }
 1143  
 
 1144  
     private List readFromFile( final File projectGoalList )
 1145  
     {
 1146  4
         BufferedReader reader = null;
 1147  
 
 1148  4
         List result = null;
 1149  
 
 1150  
         try
 1151  
         {
 1152  4
             Map composite = new CompositeMap( this.project, this.interpolationsProperties );
 1153  4
             reader = new BufferedReader( new InterpolationFilterReader( newReader( projectGoalList ), composite ) );
 1154  
 
 1155  4
             result = new ArrayList();
 1156  
 
 1157  4
             String line = null;
 1158  10
             while ( ( line = reader.readLine() ) != null )
 1159  
             {
 1160  6
                 result.addAll( collectListFromCSV( line ) );
 1161  
             }
 1162  
         }
 1163  0
         catch ( final IOException e )
 1164  
         {
 1165  0
             getLog().warn(
 1166  
                            "Failed to load goal list from file: " + projectGoalList
 1167  
                                + ". Using 'goal' parameter configured on this plugin instead." );
 1168  0
             getLog().debug( "Error reading goals file: " + projectGoalList, e );
 1169  
         }
 1170  
         finally
 1171  
         {
 1172  4
             IOUtil.close( reader );
 1173  4
         }
 1174  
 
 1175  4
         return result;
 1176  
     }
 1177  
 
 1178  
     private List collectListFromCSV( final String csv )
 1179  
     {
 1180  7
         final List result = new ArrayList();
 1181  
 
 1182  7
         if ( ( csv != null ) && ( csv.trim().length() > 0 ) )
 1183  
         {
 1184  7
             final StringTokenizer st = new StringTokenizer( csv, "," );
 1185  
 
 1186  16
             while ( st.hasMoreTokens() )
 1187  
             {
 1188  9
                 result.add( st.nextToken().trim() );
 1189  
             }
 1190  
         }
 1191  
 
 1192  7
         return result;
 1193  
     }
 1194  
 
 1195  
     protected File buildInterpolatedFile( File originalFile, File targetDirectory, String targetFileName )
 1196  
         throws MojoExecutionException
 1197  
     {
 1198  6
         File interpolatedFile = new File( targetDirectory, targetFileName );
 1199  6
         if ( interpolatedFile.exists() )
 1200  
         {
 1201  1
             interpolatedFile.delete();
 1202  
         }
 1203  6
         interpolatedFile.deleteOnExit();
 1204  6
         if ( settings.getLocalRepository() != null )
 1205  
         {
 1206  0
             if ( this.interpolationsProperties == null )
 1207  
             {
 1208  0
                 this.interpolationsProperties = new Properties();
 1209  
             }
 1210  0
             this.interpolationsProperties.put( "localRepository", settings.getLocalRepository() );
 1211  
         }
 1212  6
         Map composite = new CompositeMap( this.project, this.interpolationsProperties );
 1213  
 
 1214  
         try
 1215  
         {
 1216  6
             boolean created = interpolatedFile.createNewFile();
 1217  6
             if ( !created )
 1218  
             {
 1219  0
                 throw new MojoExecutionException( "fail to create file " + interpolatedFile.getPath() );
 1220  
             }
 1221  
         }
 1222  0
         catch ( IOException e )
 1223  
         {
 1224  0
             throw new MojoExecutionException( "fail to create file " + interpolatedFile.getPath() );
 1225  6
         }
 1226  6
         getLog().debug( "interpolate it pom to create interpolated in " + interpolatedFile.getPath() );
 1227  
 
 1228  6
         BufferedReader reader = null;
 1229  6
         Writer writer = null;
 1230  
         try
 1231  
         {
 1232  
             // interpolation with token @...@
 1233  6
             reader = new BufferedReader( new InterpolationFilterReader( ReaderFactory.newXmlReader( originalFile ),
 1234  
                                                                         composite, "@", "@" ) );
 1235  6
             writer = WriterFactory.newXmlWriter( interpolatedFile );
 1236  6
             String line = null;
 1237  177
             while ( ( line = reader.readLine() ) != null )
 1238  
             {
 1239  171
                 writer.write( line );
 1240  
             }
 1241  6
             writer.flush();
 1242  
         }
 1243  0
         catch ( IOException e )
 1244  
         {
 1245  0
             String message = "error when interpolating it pom";
 1246  0
             throw new MojoExecutionException( message, e );
 1247  
         }
 1248  
         finally
 1249  
         {
 1250  
             // IOUtil in p-u is null check and silently NPE
 1251  6
             IOUtil.close( reader );
 1252  6
             IOUtil.close( writer );
 1253  6
         }
 1254  
 
 1255  6
         if ( interpolatedFile == null )
 1256  
         {
 1257  
             // null check : normally impossibe but :-)
 1258  0
             throw new MojoExecutionException( "pom file is null after interpolation" );
 1259  
         }
 1260  6
         return interpolatedFile;
 1261  
     }
 1262  
 
 1263  
     protected List getProfiles( File projectDirectory )
 1264  
         throws MojoExecutionException
 1265  
     {
 1266  7
         if ( profilesFile == null )
 1267  
         {
 1268  4
             return profiles == null ? Collections.EMPTY_LIST : profiles;
 1269  
         }
 1270  3
         File projectProfilesFile = new File( projectDirectory, profilesFile );
 1271  3
         if ( !projectProfilesFile.exists() )
 1272  
         {
 1273  1
             return profiles == null ? Collections.EMPTY_LIST : profiles;
 1274  
         }
 1275  2
         BufferedReader reader = null;
 1276  
         try
 1277  
         {
 1278  2
             List profilesInFiles = new ArrayList();
 1279  2
             reader = new BufferedReader( newReader( projectProfilesFile ) );
 1280  2
             String line = null;
 1281  3
             while ( ( line = reader.readLine() ) != null )
 1282  
             {
 1283  1
                 profilesInFiles.addAll( collectListFromCSV( line ) );
 1284  
             }
 1285  2
             return profilesInFiles;
 1286  
         }
 1287  0
         catch ( FileNotFoundException e )
 1288  
         {
 1289  
             // as we check first if the file it should not happened
 1290  0
             throw new MojoExecutionException( projectProfilesFile + " not found ", e );
 1291  
         }
 1292  0
         catch ( IOException e )
 1293  
         {
 1294  0
             throw new MojoExecutionException( "error reading profile in file " + projectProfilesFile + " not found ",
 1295  
                                               e );
 1296  
         }
 1297  
         finally
 1298  
         {
 1299  2
             IOUtil.close( reader );
 1300  
         }
 1301  
     }
 1302  
 
 1303  
     /**
 1304  
      * Gets the (interpolated) invoker properties for an integration test.
 1305  
      * 
 1306  
      * @param projectDirectory The base directory of the IT project, must not be <code>null</code>.
 1307  
      * @return The invoker properties, may be empty but never <code>null</code>.
 1308  
      * @throws MojoExecutionException If an error occurred.
 1309  
      */
 1310  
     private Properties getInvokerProperties( final File projectDirectory )
 1311  
         throws MojoExecutionException
 1312  
     {
 1313  4
         Properties props = new Properties();
 1314  4
         if ( invokerPropertiesFile != null )
 1315  
         {
 1316  0
             File propertiesFile = new File( projectDirectory, invokerPropertiesFile );
 1317  0
             if ( propertiesFile.isFile() )
 1318  
             {
 1319  0
                 InputStream in = null;
 1320  
                 try
 1321  
                 {
 1322  0
                     in = new FileInputStream( propertiesFile );
 1323  0
                     props.load( in );
 1324  
                 }
 1325  0
                 catch ( IOException e )
 1326  
                 {
 1327  0
                     throw new MojoExecutionException( "Failed to read invoker properties: " + propertiesFile, e );
 1328  
                 }
 1329  
                 finally
 1330  
                 {
 1331  0
                     IOUtil.close( in );
 1332  0
                 }
 1333  
             }
 1334  
 
 1335  0
             Map filter = new CompositeMap( project, this.interpolationsProperties );
 1336  0
             Interpolator interpolator = new RegexBasedInterpolator();
 1337  0
             interpolator.addValueSource( new MapBasedValueSource( filter ) );
 1338  0
             for ( Iterator it = props.keySet().iterator(); it.hasNext(); )
 1339  
             {
 1340  0
                 String key = (String) it.next();
 1341  0
                 String value = props.getProperty( key );
 1342  
                 try
 1343  
                 {
 1344  0
                     value = interpolator.interpolate( value, "" );
 1345  
                 }
 1346  0
                 catch ( InterpolationException e )
 1347  
                 {
 1348  0
                     throw new MojoExecutionException( "Failed to interpolate invoker properties: " + propertiesFile,
 1349  
                                                       e );
 1350  0
                 }
 1351  0
                 props.setProperty( key, value );
 1352  
             }
 1353  
         }
 1354  4
         return props;
 1355  
     }
 1356  
 
 1357  
     /**
 1358  
      * Configures the specified invocation request from the given invoker properties. Settings not present in the
 1359  
      * invoker properties will be left unchanged in the invocation request.
 1360  
      * 
 1361  
      * @param request The invocation request to configure, must not be <code>null</code>.
 1362  
      * @param properties The invoker properties used to configure the invocation, must not be <code>null</code>.
 1363  
      * @return The configured invocation request.
 1364  
      */
 1365  
     private InvocationRequest configureInvocation( InvocationRequest request, Properties properties )
 1366  
     {
 1367  4
         String goals = properties.getProperty( "invoker.goals" );
 1368  4
         if ( goals != null )
 1369  
         {
 1370  0
             request.setGoals( new ArrayList( Arrays.asList( goals.split( "[,\\s]+" ) ) ) );
 1371  
         }
 1372  
 
 1373  4
         String profiles = properties.getProperty( "invoker.profiles" );
 1374  4
         if ( profiles != null )
 1375  
         {
 1376  0
             request.setProfiles( new ArrayList( Arrays.asList( profiles.split( "[,\\s]+" ) ) ) );
 1377  
         }
 1378  
 
 1379  4
         String opts = properties.getProperty( "invoker.mavenOpts" );
 1380  4
         if ( opts != null )
 1381  
         {
 1382  0
             request.setMavenOpts( opts );
 1383  
         }
 1384  
 
 1385  4
         String failureBehavior = properties.getProperty( "invoker.failureBehavior" );
 1386  4
         if ( failureBehavior != null )
 1387  
         {
 1388  0
             request.setFailureBehavior( failureBehavior );
 1389  
         }
 1390  
 
 1391  4
         String nonRecursive = properties.getProperty( "invoker.nonRecursive" );
 1392  4
         if ( nonRecursive != null )
 1393  
         {
 1394  0
             request.setRecursive( !Boolean.valueOf( nonRecursive ).booleanValue() );
 1395  
         }
 1396  
 
 1397  4
         return request;
 1398  
     }
 1399  
 
 1400  
 }