Coverage Report - org.apache.maven.plugin.surefire.SurefirePlugin
 
Classes in this File Line Coverage Branch Coverage Complexity
SurefirePlugin
0% 
0% 
6.545
 
 1  
 package org.apache.maven.plugin.surefire;
 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 org.apache.maven.artifact.Artifact;
 23  
 import org.apache.maven.artifact.factory.ArtifactFactory;
 24  
 import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
 25  
 import org.apache.maven.artifact.repository.ArtifactRepository;
 26  
 import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
 27  
 import org.apache.maven.artifact.resolver.ArtifactResolutionException;
 28  
 import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
 29  
 import org.apache.maven.artifact.resolver.ArtifactResolver;
 30  
 import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
 31  
 import org.apache.maven.artifact.resolver.filter.ExcludesArtifactFilter;
 32  
 import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
 33  
 import org.apache.maven.artifact.versioning.VersionRange;
 34  
 import org.apache.maven.plugin.AbstractMojo;
 35  
 import org.apache.maven.plugin.MojoExecutionException;
 36  
 import org.apache.maven.plugin.MojoFailureException;
 37  
 import org.apache.maven.surefire.booter.ForkConfiguration;
 38  
 import org.apache.maven.surefire.booter.SurefireBooter;
 39  
 import org.apache.maven.surefire.booter.SurefireBooterForkException;
 40  
 import org.apache.maven.surefire.booter.SurefireExecutionException;
 41  
 import org.apache.maven.surefire.report.BriefConsoleReporter;
 42  
 import org.apache.maven.surefire.report.BriefFileReporter;
 43  
 import org.apache.maven.surefire.report.ConsoleReporter;
 44  
 import org.apache.maven.surefire.report.DetailedConsoleReporter;
 45  
 import org.apache.maven.surefire.report.FileReporter;
 46  
 import org.apache.maven.surefire.report.ForkingConsoleReporter;
 47  
 import org.apache.maven.surefire.report.XMLReporter;
 48  
 import org.codehaus.plexus.util.StringUtils;
 49  
 
 50  
 import java.io.File;
 51  
 import java.util.ArrayList;
 52  
 import java.util.Arrays;
 53  
 import java.util.Collections;
 54  
 import java.util.HashMap;
 55  
 import java.util.Iterator;
 56  
 import java.util.List;
 57  
 import java.util.Map;
 58  
 import java.util.Properties;
 59  
 
 60  
 /**
 61  
  * Run tests using Surefire.
 62  
  *
 63  
  * @author Jason van Zyl
 64  
  * @version $Id: SurefirePlugin.java 493522 2007-01-06 18:08:15Z jvanzyl $
 65  
  * @requiresDependencyResolution test
 66  
  * @goal test
 67  
  * @phase test
 68  
  */
 69  0
 public class SurefirePlugin
 70  
     extends AbstractMojo
 71  
 {
 72  
     /**
 73  
      * Set this to 'true' to bypass unit tests entirely. Its use is NOT RECOMMENDED, but quite convenient on occasion.
 74  
      *
 75  
      * @parameter expression="${maven.test.skip}"
 76  
      */
 77  
     private boolean skip;
 78  
 
 79  
     /**
 80  
      * Set this to 'true' to bypass unit tests execution, but still compile them. Its use is NOT RECOMMENDED, but quite convenient on occasion.
 81  
      *
 82  
      * @parameter expression="${maven.test.skip.exec}"
 83  
      */
 84  
     private boolean skipExec;
 85  
 
 86  
     /**
 87  
      * Set this to true to ignore a failure during testing. Its use is NOT RECOMMENDED, but quite convenient on occasion.
 88  
      *
 89  
      * @parameter expression="${maven.test.failure.ignore}"
 90  
      */
 91  
     private boolean testFailureIgnore;
 92  
 
 93  
     /**
 94  
      * The base directory of the project being tested. This can be obtained in your unit test by System.getProperty("basedir").
 95  
      *
 96  
      * @parameter expression="${basedir}"
 97  
      * @required
 98  
      */
 99  
     private File basedir;
 100  
 
 101  
     // FIXME this field is not used
 102  
     /**
 103  
      * The directory containing generated classes of the project being tested.
 104  
      *
 105  
      * @parameter expression="${project.build.outputDirectory}"
 106  
      * @required
 107  
      */
 108  
     private File classesDirectory;
 109  
 
 110  
     /**
 111  
      * The directory containing generated test classes of the project being tested.
 112  
      *
 113  
      * @parameter expression="${project.build.testOutputDirectory}"
 114  
      * @required
 115  
      */
 116  
     private File testClassesDirectory;
 117  
 
 118  
     /**
 119  
      * The classpath elements of the project being tested.
 120  
      *
 121  
      * @parameter expression="${project.testClasspathElements}"
 122  
      * @required
 123  
      * @readonly
 124  
      */
 125  
     private List classpathElements;
 126  
 
 127  
     /**
 128  
      * Base directory where all reports are written to.
 129  
      *
 130  
      * @parameter expression="${project.build.directory}/surefire-reports"
 131  
      */
 132  
     private File reportsDirectory;
 133  
 
 134  
     /**
 135  
      * The test source directory containing test class sources.
 136  
      *
 137  
      * @parameter expression="${project.build.testSourceDirectory}"
 138  
      * @required
 139  
      */
 140  
     private File testSourceDirectory;
 141  
 
 142  
     /**
 143  
      * Specify this parameter(can be a comma separated list) if you want to use the test pattern matching notation, Ant pattern matching, to select tests to run.
 144  
      * The Ant pattern will be used to create an include pattern formatted like <code>**&#47;${test}.java</code>
 145  
      * When used, the <code>includes</code> and <code>excludes</code> patterns parameters are ignored.
 146  
      *
 147  
      * @parameter expression="${test}"
 148  
      */
 149  
     private String test;
 150  
 
 151  
     /**
 152  
      * List of patterns (separated by commas) used to specify the tests that should be included in testing.
 153  
      * When not specified and when the <code>test</code> parameter is not specified, the default includes will be
 154  
      * <code>**&#47;Test*.java   **&#47;*Test.java   **&#47;*TestCase.java</code>
 155  
      *
 156  
      * @parameter
 157  
      */
 158  
     private List includes;
 159  
 
 160  
     /**
 161  
      * List of patterns (separated by commas) used to specify the tests that should be excluded in testing.
 162  
      * When not specified and when the <code>test</code> parameter is not specified, the default excludes will be
 163  
      * <code>**&#47;Abstract*Test.java  **&#47;Abstract*TestCase.java **&#47;*$*</code>
 164  
      *
 165  
      * @parameter
 166  
      */
 167  
     private List excludes;
 168  
 
 169  
     /**
 170  
      * ArtifactRepository of the localRepository. To obtain the directory of localRepository in unit tests use System.setProperty( "localRepository").
 171  
      *
 172  
      * @parameter expression="${localRepository}"
 173  
      * @required
 174  
      * @readonly
 175  
      */
 176  
     private ArtifactRepository localRepository;
 177  
 
 178  
     /**
 179  
      * List of System properties to pass to the JUnit tests.
 180  
      *
 181  
      * @parameter
 182  
      */
 183  
     private Properties systemProperties;
 184  
 
 185  
     /**
 186  
      * Map of of plugin artifacts.
 187  
      *
 188  
      * @parameter expression="${plugin.artifactMap}"
 189  
      * @required
 190  
      * @readonly
 191  
      */
 192  
     private Map pluginArtifactMap;
 193  
 
 194  
     /**
 195  
      * Map of of project artifacts.
 196  
      *
 197  
      * @parameter expression="${project.artifactMap}"
 198  
      * @required
 199  
      * @readonly
 200  
      */
 201  
     private Map projectArtifactMap;
 202  
 
 203  
     /**
 204  
      * Option to print summary of test suites or just print the test cases that has errors.
 205  
      *
 206  
      * @parameter expression="${surefire.printSummary}"
 207  
      * default-value="true"
 208  
      */
 209  
     private boolean printSummary;
 210  
 
 211  
     /**
 212  
      * Selects the formatting for the test report to be generated.  Can be set as brief or plain.
 213  
      *
 214  
      * @parameter expression="${surefire.reportFormat}"
 215  
      * default-value="brief"
 216  
      */
 217  
     private String reportFormat;
 218  
 
 219  
     /**
 220  
      * Option to generate a file test report or just output the test report to the console.
 221  
      *
 222  
      * @parameter expression="${surefire.useFile}"
 223  
      * default-value="true"
 224  
      */
 225  
     private boolean useFile;
 226  
 
 227  
     /**
 228  
      * When forking, set this to true to redirect the unit test standard output to a file
 229  
      * (found in reportsDirectory/testName-output.txt).
 230  
      *
 231  
      * @parameter expression="${maven.test.redirectTestOutputToFile}" default-value="false"
 232  
      */
 233  
     private boolean redirectTestOutputToFile;
 234  
 
 235  
     /**
 236  
      * Option to specify the forking mode. Can be "never", "once" or "always".
 237  
      * "none" and "pertest" are also accepted for backwards compatibility.
 238  
      *
 239  
      * @parameter expression="${forkMode}" default-value="once"
 240  
      */
 241  
     private String forkMode;
 242  
 
 243  
     /**
 244  
      * Option to specify the jvm (or path to the java executable) to use with
 245  
      * the forking options. For the default, the jvm will be the same as the one
 246  
      * used to run Maven.
 247  
      *
 248  
      * @parameter expression="${jvm}"
 249  
      */
 250  
     private String jvm;
 251  
 
 252  
     /**
 253  
      * Arbitrary options to set on the command line.
 254  
      *
 255  
      * @parameter expression="${argLine}"
 256  
      */
 257  
     private String argLine;
 258  
 
 259  
     /**
 260  
      * Additional environments to set on the command line.
 261  
      *
 262  
      * @parameter
 263  
      */
 264  0
     private Map environmentVariables = new HashMap();
 265  
 
 266  
     /**
 267  
      * Command line working directory.
 268  
      *
 269  
      * @parameter
 270  
      */
 271  
     private File workingDirectory;
 272  
 
 273  
     /**
 274  
      * When false it makes tests run using the standard classloader delegation instead of the default
 275  
      * Maven isolated classloader. Only used when forking (forkMode is not "none").<br/>
 276  
      * Setting it to false helps with some problems caused by conflicts between
 277  
      * xml parsers in the classpath and the Java 5 provider parser.
 278  
      *
 279  
      * @parameter expression="${childDelegation}"
 280  
      * default-value="false"
 281  
      */
 282  
     private boolean childDelegation;
 283  
 
 284  
     /**
 285  
      * Groups for this test. Only classes/methods/etc decorated with one of the
 286  
      * groups specified here will be included in test run, if specified.
 287  
      *
 288  
      * @parameter expression="${groups}"
 289  
      */
 290  
     private String groups;
 291  
 
 292  
     /**
 293  
      * Excluded groups. Any methods/classes/etc with one of the groups specified in this
 294  
      * list will specifically not be run.
 295  
      *
 296  
      * @parameter expression="${excludedGroups}"
 297  
      */
 298  
     private String excludedGroups;
 299  
 
 300  
     /**
 301  
      * List of TestNG suite xml file locations, seperated by commas. It should be noted that
 302  
      * if suiteXmlFiles is specified, <b>no</b> other tests will be run, ignoring other parameters,
 303  
      * like includes and excludes.
 304  
      *
 305  
      * @parameter
 306  
      */
 307  
     private File[] suiteXmlFiles;
 308  
 
 309  
     /**
 310  
      * The attribute thread-count allows you to specify how many threads should be allocated
 311  
      * for this execution. Only makes sense to use in conjunction with parallel.
 312  
      *
 313  
      * @parameter expression="${threadCount}"
 314  
      * default-value="5"
 315  
      */
 316  
     private int threadCount;
 317  
 
 318  
     /**
 319  
      * When you use the parallel attribute, TestNG will try to run all your test methods in
 320  
      * separate threads, except for methods that depend on each other, which will be run in
 321  
      * the same thread in order to respect their order of execution.
 322  
      *
 323  
      * @parameter expression="${parallel}"
 324  
      * default-value="false"
 325  
      * @todo test how this works with forking, and console/file output parallelism
 326  
      */
 327  
     private boolean parallel;
 328  
 
 329  
     /**
 330  
      * Whether to trim the stack trace in the reports to just the lines within the test, or show the full trace.
 331  
      *
 332  
      * @parameter expression="${trimStackTrace}" default-value="true"
 333  
      */
 334  
     private boolean trimStackTrace;
 335  
 
 336  
     /**
 337  
      * Resolves the artifacts needed.
 338  
      *
 339  
      * @component
 340  
      */
 341  
     private ArtifactResolver artifactResolver;
 342  
 
 343  
     /**
 344  
      * Creates the artifact
 345  
      *
 346  
      * @component
 347  
      */
 348  
     private ArtifactFactory artifactFactory;
 349  
 
 350  
     /**
 351  
      * The plugin remote repositories declared in the pom.
 352  
      *
 353  
      * @parameter expression="${project.pluginArtifactRepositories}"
 354  
      */
 355  
     private List remoteRepositories;
 356  
 
 357  
     /**
 358  
      * For retrieval of artifact's metadata.
 359  
      *
 360  
      * @component
 361  
      */
 362  
     private ArtifactMetadataSource metadataSource;
 363  
 
 364  
     private static final String BRIEF_REPORT_FORMAT = "brief";
 365  
 
 366  
     private static final String PLAIN_REPORT_FORMAT = "plain";
 367  
 
 368  
     private Properties originalSystemProperties;
 369  
 
 370  
     /**
 371  
      * Flag to disable the generation of report files in xml format.
 372  
      *
 373  
      * @parameter expression="${disableXmlReport}" default-value="false"
 374  
      */
 375  
     private boolean disableXmlReport;
 376  
 
 377  
     /**
 378  
      * Option to pass dependencies to the system's classloader instead of using an isolated class loader when
 379  
      * forking. Prevents problems with JDKs which implement the service provider lookup mechanism by using
 380  
      * the system's classloader.
 381  
      *
 382  
      * @parameter expression="${surefire.useSystemClassLoader}" default-value="false"
 383  
      */
 384  
     private boolean useSystemClassLoader;
 385  
 
 386  
     public void execute()
 387  
         throws MojoExecutionException, MojoFailureException
 388  
     {
 389  0
         if ( verifyParameters() )
 390  
         {
 391  0
             SurefireBooter surefireBooter = constructSurefireBooter();
 392  
 
 393  0
             getLog().info( "Surefire report directory: " + reportsDirectory );
 394  
 
 395  
             boolean success;
 396  
             try
 397  
             {
 398  0
                 success = surefireBooter.run();
 399  
             }
 400  0
             catch ( SurefireBooterForkException e )
 401  
             {
 402  0
                 throw new MojoExecutionException( e.getMessage(), e );
 403  
             }
 404  0
             catch ( SurefireExecutionException e )
 405  
             {
 406  0
                 throw new MojoExecutionException( e.getMessage(), e );
 407  0
             }
 408  
 
 409  0
             if ( originalSystemProperties != null )
 410  
             {
 411  
                 // restore system properties
 412  0
                 System.setProperties( originalSystemProperties );
 413  
             }
 414  
 
 415  0
             if ( !success )
 416  
             {
 417  0
                 String msg = "There are test failures.";
 418  
 
 419  0
                 if ( testFailureIgnore )
 420  
                 {
 421  0
                     getLog().error( msg );
 422  0
                 }
 423  
                 else
 424  
                 {
 425  0
                     throw new MojoFailureException( msg );
 426  
                 }
 427  
             }
 428  
         }
 429  0
     }
 430  
 
 431  
     private boolean verifyParameters()
 432  
         throws MojoFailureException
 433  
     {
 434  0
         if ( skip || skipExec )
 435  
         {
 436  0
             getLog().info( "Tests are skipped." );
 437  0
             return false;
 438  
         }
 439  0
         else if ( !testClassesDirectory.exists() )
 440  
         {
 441  0
             getLog().info( "No tests to run." );
 442  0
             return false;
 443  
         }
 444  
 
 445  0
         if ( parallel )
 446  
         {
 447  0
             if ( threadCount < 1 )
 448  
             {
 449  0
                 throw new MojoFailureException( "Must have at least one thread in parallel mode" );
 450  
             }
 451  
         }
 452  
 
 453  0
         if ( useSystemClassLoader && ForkConfiguration.FORK_NEVER.equals( forkMode ) )
 454  
         {
 455  0
             getLog().warn( "useSystemClassloader=true setting has no effect when not forking" );
 456  
         }
 457  
 
 458  0
         return true;
 459  
     }
 460  
 
 461  
     private SurefireBooter constructSurefireBooter()
 462  
         throws MojoExecutionException, MojoFailureException
 463  
     {
 464  0
         SurefireBooter surefireBooter = new SurefireBooter();
 465  
 
 466  0
         Artifact surefireArtifact = (Artifact) pluginArtifactMap.get( "org.apache.maven.surefire:surefire-booter" );
 467  0
         if ( surefireArtifact == null )
 468  
         {
 469  0
             throw new MojoExecutionException( "Unable to locate surefire-booter in the list of plugin artifacts" );
 470  
         }
 471  
 
 472  0
         surefireArtifact.isSnapshot(); // TODO: this is ridiculous, but it fixes getBaseVersion to be -SNAPSHOT if needed
 473  
 
 474  
         Artifact junitArtifact;
 475  
         Artifact testNgArtifact;
 476  
         try
 477  
         {
 478  0
             addArtifact( surefireBooter, surefireArtifact );
 479  
 
 480  0
             junitArtifact = (Artifact) projectArtifactMap.get( "junit:junit" );
 481  
 
 482  
             // TODO: this is pretty manual, but I'd rather not require the plugin > dependencies section right now
 483  0
             testNgArtifact = (Artifact) projectArtifactMap.get( "org.testng:testng" );
 484  
 
 485  0
             if ( testNgArtifact != null )
 486  
             {
 487  0
                 addArtifact(surefireBooter, testNgArtifact);
 488  
 
 489  0
                 VersionRange range = VersionRange.createFromVersionSpec( "[4.7,)" );
 490  0
                 if ( !range.containsVersion( testNgArtifact.getSelectedVersion() ) )
 491  
                 {
 492  0
                     throw new MojoFailureException(
 493  
                         "TestNG support requires version 4.7 or above. You have declared version " +
 494  
                             testNgArtifact.getVersion() );
 495  
                 }
 496  
 
 497  
                 // The plugin uses a JDK based profile to select the right testng. We might be explicity using a
 498  
                 // different one since its based on the source level, not the JVM. Prune using the filter.
 499  0
                 addProvider( surefireBooter, "surefire-testng", surefireArtifact.getBaseVersion(), testNgArtifact );
 500  0
             }
 501  0
             else if (junitArtifact != null && junitArtifact.getBaseVersion().startsWith("4"))
 502  
             {
 503  0
                 addProvider( surefireBooter, "surefire-junit4", surefireArtifact.getBaseVersion(), null );
 504  0
             }
 505  
             else
 506  
             {
 507  
                 // add the JUnit provider as default - it doesn't require JUnit to be present,
 508  
                 // since it supports POJO tests.
 509  0
                 addProvider( surefireBooter, "surefire-junit", surefireArtifact.getBaseVersion(), null );
 510  
             }
 511  
         }
 512  0
         catch ( ArtifactNotFoundException e )
 513  
         {
 514  0
             throw new MojoExecutionException(
 515  
                 "Unable to locate required surefire provider dependency: " + e.getMessage(), e );
 516  
         }
 517  0
         catch ( InvalidVersionSpecificationException e )
 518  
         {
 519  0
             throw new MojoExecutionException( "Error determining the TestNG version requested: " + e.getMessage(), e );
 520  
         }
 521  0
         catch ( ArtifactResolutionException e )
 522  
         {
 523  0
             throw new MojoExecutionException( "Error to resolving surefire provider dependency: " + e.getMessage(), e );
 524  0
         }
 525  
 
 526  0
         if ( suiteXmlFiles != null && suiteXmlFiles.length > 0 )
 527  
         {
 528  0
             if ( testNgArtifact == null )
 529  
             {
 530  0
                 throw new MojoExecutionException( "suiteXmlFiles is configured, but there is no TestNG dependency" );
 531  
             }
 532  0
             for ( int i = 0; i < suiteXmlFiles.length; i++ )
 533  
             {
 534  0
                 File file = suiteXmlFiles[i];
 535  0
                 if ( file.exists() )
 536  
                 {
 537  0
                     surefireBooter.addTestSuite( "org.apache.maven.surefire.testng.TestNGXmlTestSuite",
 538  
                                                  new Object[]{file, testSourceDirectory.getAbsolutePath()} );
 539  
                 }
 540  
             }
 541  0
         }
 542  
         else
 543  
         {
 544  
             List includes;
 545  
             List excludes;
 546  
 
 547  0
             if ( test != null )
 548  
             {
 549  
                 // Check to see if we are running a single test. The raw parameter will
 550  
                 // come through if it has not been set.
 551  
 
 552  
                 // FooTest -> **/FooTest.java
 553  
 
 554  0
                 includes = new ArrayList();
 555  
 
 556  0
                 excludes = new ArrayList();
 557  
 
 558  0
                 String[] testRegexes = StringUtils.split( test, "," );
 559  
 
 560  0
                 for ( int i = 0; i < testRegexes.length; i++ )
 561  
                 {
 562  0
                     includes.add( "**/" + testRegexes[i] + ".java" );
 563  
                 }
 564  0
             }
 565  
             else
 566  
             {
 567  0
                 includes = this.includes;
 568  
 
 569  0
                 excludes = this.excludes;
 570  
 
 571  
                 // defaults here, qdox doesn't like the end javadoc value
 572  
                 // Have to wrap in an ArrayList as surefire expects an ArrayList instead of a List for some reason
 573  0
                 if ( includes == null || includes.size() == 0 )
 574  
                 {
 575  0
                     includes = new ArrayList(
 576  
                         Arrays.asList( new String[]{"**/Test*.java", "**/*Test.java", "**/*TestCase.java"} ) );
 577  
                 }
 578  0
                 if ( excludes == null || excludes.size() == 0 )
 579  
                 {
 580  0
                     excludes = new ArrayList(
 581  
                         Arrays.asList( new String[]{"**/Abstract*Test.java", "**/Abstract*TestCase.java", "**/*$*"} ) );
 582  
                 }
 583  
             }
 584  
 
 585  0
             if ( testNgArtifact != null )
 586  
             {
 587  0
                 surefireBooter.addTestSuite( "org.apache.maven.surefire.testng.TestNGDirectoryTestSuite", new Object[]{
 588  
                     testClassesDirectory, includes, excludes, groups, excludedGroups, Boolean.valueOf( parallel ),
 589  
                     new Integer( threadCount ), testSourceDirectory.getAbsolutePath()} );
 590  0
             }
 591  
             else
 592  
             {
 593  
                     String junitDirectoryTestSuite;
 594  0
                     if (junitArtifact.getBaseVersion().startsWith("4")) 
 595  
                     {
 596  0
                             junitDirectoryTestSuite = "org.apache.maven.surefire.junit4.JUnit4DirectoryTestSuite";
 597  0
                     } 
 598  
                     else
 599  
                     {
 600  0
                             junitDirectoryTestSuite = "org.apache.maven.surefire.junit.JUnitDirectoryTestSuite";
 601  
                     }
 602  
                             
 603  
                 // fall back to JUnit, which also contains POJO support. Also it can run
 604  
                 // classes compiled against JUnit since it has a dependency on JUnit itself.
 605  0
                 surefireBooter.addTestSuite( junitDirectoryTestSuite,
 606  
                                              new Object[]{testClassesDirectory, includes, excludes} );
 607  
             }
 608  
         }
 609  
 
 610  
         // ----------------------------------------------------------------------
 611  
         //
 612  
         // ----------------------------------------------------------------------
 613  
 
 614  0
         getLog().debug( "Test Classpath :" );
 615  
 
 616  
         // no need to add classes/test classes directory here - they are in the classpath elements already
 617  
 
 618  0
         for ( Iterator i = classpathElements.iterator(); i.hasNext(); )
 619  
         {
 620  0
             String classpathElement = (String) i.next();
 621  
 
 622  0
             getLog().debug( "  " + classpathElement );
 623  
 
 624  0
             surefireBooter.addClassPathUrl( classpathElement );
 625  0
         }
 626  
 
 627  
         // ----------------------------------------------------------------------
 628  
         // Forking
 629  
         // ----------------------------------------------------------------------
 630  
 
 631  0
         ForkConfiguration fork = new ForkConfiguration();
 632  
 
 633  0
         fork.setForkMode( forkMode );
 634  
 
 635  0
         processSystemProperties( !fork.isForking() );
 636  
 
 637  0
         if ( getLog().isDebugEnabled() )
 638  
         {
 639  0
             showMap( systemProperties, "system property" );
 640  
         }
 641  
 
 642  0
         if ( fork.isForking() )
 643  
         {
 644  0
             fork.setSystemProperties( systemProperties );
 645  
 
 646  0
             if ( jvm == null || "".equals( jvm ) )
 647  
             {
 648  
                 // use the same JVM as the one used to run Maven (the "java.home" one)
 649  0
                 jvm = System.getProperty( "java.home" ) + File.separator + "bin" + File.separator + "java";
 650  0
                 getLog().debug( "Using JVM: " + jvm );
 651  
             }
 652  
 
 653  0
             fork.setJvmExecutable( jvm );
 654  
 
 655  0
             if ( workingDirectory != null )
 656  
             {
 657  0
                 fork.setWorkingDirectory( workingDirectory );
 658  0
             }
 659  
             else
 660  
             {
 661  0
                 fork.setWorkingDirectory( basedir );
 662  
             }
 663  
 
 664  0
             fork.setArgLine( argLine );
 665  
 
 666  0
             fork.setEnvironmentVariables( environmentVariables );
 667  
 
 668  0
             if ( getLog().isDebugEnabled() )
 669  
             {
 670  0
                 showMap( environmentVariables, "environment variable" );
 671  
 
 672  0
                 fork.setDebug( true );
 673  
             }
 674  
         }
 675  
 
 676  0
         surefireBooter.setRedirectTestOutputToFile( redirectTestOutputToFile );
 677  
 
 678  0
         surefireBooter.setForkConfiguration( fork );
 679  
 
 680  0
         surefireBooter.setChildDelegation( childDelegation );
 681  
 
 682  0
         surefireBooter.setReportsDirectory( reportsDirectory );
 683  
 
 684  0
         surefireBooter.setUseSystemClassLoader( useSystemClassLoader );
 685  
 
 686  0
         addReporters( surefireBooter, fork.isForking() );
 687  
 
 688  0
         return surefireBooter;
 689  
     }
 690  
 
 691  
     private void showMap( Map map, String setting )
 692  
     {
 693  0
         for ( Iterator i = map.keySet().iterator(); i.hasNext(); )
 694  
         {
 695  0
             String key = (String) i.next();
 696  0
             String value = (String) map.get( key );
 697  0
             getLog().debug( "Setting " + setting + " [" + key + "]=[" + value + "]" );
 698  0
         }
 699  0
     }
 700  
 
 701  
     private void addProvider( SurefireBooter surefireBooter, String provider, String version,
 702  
                               Artifact filteredArtifact )
 703  
         throws ArtifactNotFoundException, ArtifactResolutionException
 704  
     {
 705  0
         Artifact providerArtifact = artifactFactory.createDependencyArtifact( "org.apache.maven.surefire", provider,
 706  
                                                                               VersionRange.createFromVersion( version ),
 707  
                                                                               "jar", null, Artifact.SCOPE_TEST );
 708  0
         ArtifactResolutionResult result = resolveArtifact( filteredArtifact, providerArtifact );
 709  
 
 710  0
         for ( Iterator i = result.getArtifacts().iterator(); i.hasNext(); )
 711  
         {
 712  0
             Artifact artifact = (Artifact) i.next();
 713  
 
 714  0
             getLog().debug( "Adding to surefire test classpath: " + artifact.getFile().getAbsolutePath() );
 715  
 
 716  0
             surefireBooter.addSurefireClassPathUrl( artifact.getFile().getAbsolutePath() );
 717  0
         }
 718  0
     }
 719  
 
 720  
     private ArtifactResolutionResult resolveArtifact( Artifact filteredArtifact, Artifact providerArtifact )
 721  
         throws ArtifactResolutionException, ArtifactNotFoundException
 722  
     {
 723  0
         ArtifactFilter filter = null;
 724  0
         if ( filteredArtifact != null )
 725  
         {
 726  0
             filter = new ExcludesArtifactFilter(
 727  
                 Collections.singletonList( filteredArtifact.getGroupId() + ":" + filteredArtifact.getArtifactId() ) );
 728  
         }
 729  
 
 730  0
         Artifact originatingArtifact = artifactFactory.createBuildArtifact( "dummy", "dummy", "1.0", "jar" );
 731  
 
 732  0
         return artifactResolver.resolveTransitively( Collections.singleton( providerArtifact ), originatingArtifact,
 733  
                                                      localRepository, remoteRepositories, metadataSource, filter );
 734  
     }
 735  
 
 736  
     private void addArtifact( SurefireBooter surefireBooter, Artifact surefireArtifact )
 737  
         throws ArtifactNotFoundException, ArtifactResolutionException
 738  
     {
 739  0
         ArtifactResolutionResult result = resolveArtifact( null, surefireArtifact );
 740  
 
 741  0
         for ( Iterator i = result.getArtifacts().iterator(); i.hasNext(); )
 742  
         {
 743  0
             Artifact artifact = (Artifact) i.next();
 744  
 
 745  0
             getLog().debug( "Adding to surefire booter test classpath: " + artifact.getFile().getAbsolutePath() );
 746  
 
 747  0
             surefireBooter.addSurefireBootClassPathUrl( artifact.getFile().getAbsolutePath() );
 748  0
         }
 749  0
     }
 750  
 
 751  
     protected void processSystemProperties( boolean setInSystem )
 752  
     {
 753  0
         if ( systemProperties == null )
 754  
         {
 755  0
             systemProperties = new Properties();
 756  
         }
 757  
 
 758  0
         originalSystemProperties = (Properties) System.getProperties().clone();
 759  
 
 760  0
         systemProperties.setProperty( "basedir", basedir.getAbsolutePath() );
 761  
 
 762  0
         systemProperties.setProperty( "localRepository", localRepository.getBasedir() );
 763  
 
 764  0
         if ( setInSystem )
 765  
         {
 766  
             // Add all system properties configured by the user
 767  0
             Iterator iter = systemProperties.keySet().iterator();
 768  
 
 769  0
             while ( iter.hasNext() )
 770  
             {
 771  0
                 String key = (String) iter.next();
 772  
 
 773  0
                 String value = systemProperties.getProperty( key );
 774  
 
 775  0
                 System.setProperty( key, value );
 776  0
             }
 777  
         }
 778  0
     }
 779  
 
 780  
     /**
 781  
      * <p> Adds Reporters that will generate reports with different formatting.
 782  
      * <p> The Reporter that will be added will be based on the value of the parameter
 783  
      * useFile, reportFormat, and printSummary.
 784  
      *
 785  
      * @param surefireBooter The surefire booter that will run tests.
 786  
      * @param forking
 787  
      */
 788  
     private void addReporters( SurefireBooter surefireBooter, boolean forking )
 789  
     {
 790  0
         Boolean trimStackTrace = Boolean.valueOf( this.trimStackTrace );
 791  0
         if ( useFile )
 792  
         {
 793  0
             if ( printSummary )
 794  
             {
 795  0
                 if ( forking )
 796  
                 {
 797  0
                     surefireBooter.addReport( ForkingConsoleReporter.class.getName(), new Object[]{trimStackTrace} );
 798  0
                 }
 799  
                 else
 800  
                 {
 801  0
                     surefireBooter.addReport( ConsoleReporter.class.getName(), new Object[]{trimStackTrace} );
 802  
                 }
 803  
             }
 804  
 
 805  0
             if ( BRIEF_REPORT_FORMAT.equals( reportFormat ) )
 806  
             {
 807  0
                 surefireBooter.addReport( BriefFileReporter.class.getName(),
 808  
                                           new Object[]{reportsDirectory, trimStackTrace} );
 809  0
             }
 810  0
             else if ( PLAIN_REPORT_FORMAT.equals( reportFormat ) )
 811  
             {
 812  0
                 surefireBooter.addReport( FileReporter.class.getName(),
 813  
                                           new Object[]{reportsDirectory, trimStackTrace} );
 814  0
             }
 815  
         }
 816  
         else
 817  
         {
 818  0
             if ( BRIEF_REPORT_FORMAT.equals( reportFormat ) )
 819  
             {
 820  0
                 surefireBooter.addReport( BriefConsoleReporter.class.getName(), new Object[]{trimStackTrace} );
 821  0
             }
 822  0
             else if ( PLAIN_REPORT_FORMAT.equals( reportFormat ) )
 823  
             {
 824  0
                 surefireBooter.addReport( DetailedConsoleReporter.class.getName(), new Object[]{trimStackTrace} );
 825  
             }
 826  
         }
 827  
 
 828  0
         if ( !disableXmlReport )
 829  
         {
 830  0
             surefireBooter.addReport( XMLReporter.class.getName(), new Object[]{reportsDirectory, trimStackTrace} );
 831  
         }
 832  0
     }
 833  
 
 834  
     /**
 835  
      * @return SurefirePlugin Returns the skipExec.
 836  
      */
 837  
     public boolean isSkipExec()
 838  
     {
 839  0
         return this.skipExec;
 840  
     }
 841  
 
 842  
     /**
 843  
      * @param skipExec the skipExec to set
 844  
      */
 845  
     public void setSkipExec( boolean skipExec )
 846  
     {
 847  0
         this.skipExec = skipExec;
 848  0
     }
 849  
 }