You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by kr...@apache.org on 2013/04/07 12:41:19 UTC

git commit: o Added support for executing provider without booter

Updated Branches:
  refs/heads/master f00c32ec7 -> aae5a8c99


o Added support for executing provider without booter


Project: http://git-wip-us.apache.org/repos/asf/maven-surefire/repo
Commit: http://git-wip-us.apache.org/repos/asf/maven-surefire/commit/aae5a8c9
Tree: http://git-wip-us.apache.org/repos/asf/maven-surefire/tree/aae5a8c9
Diff: http://git-wip-us.apache.org/repos/asf/maven-surefire/diff/aae5a8c9

Branch: refs/heads/master
Commit: aae5a8c99bdccabbdf315f8118ea6c6e8fe967de
Parents: f00c32e
Author: Kristian Rosenvold <kr...@apache.org>
Authored: Sun Apr 7 12:16:23 2013 +0200
Committer: Kristian Rosenvold <kr...@apache.org>
Committed: Sun Apr 7 12:41:13 2013 +0200

----------------------------------------------------------------------
 .../plugin/surefire/AbstractSurefireMojo.java      |   52 ++++------
 .../surefire/booterclient/ForkConfiguration.java   |   43 +++++----
 .../plugin/surefire/booterclient/ForkStarter.java  |   75 ++++++++-------
 .../booterclient/ForkConfigurationTest.java        |    9 +-
 .../apache/maven/surefire/booter/Classpath.java    |   13 +++
 .../surefire/booter/ClasspathConfiguration.java    |    5 +
 .../maven/surefire/booter/ProviderFactory.java     |    3 +-
 .../surefire/booter/StartupConfiguration.java      |   51 ++++++++++-
 surefire-shadefire/pom.xml                         |    4 +-
 9 files changed, 161 insertions(+), 94 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/aae5a8c9/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
index 2ff2c58..815c4fa 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
@@ -32,6 +32,7 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Properties;
 import java.util.Set;
+
 import org.apache.maven.artifact.Artifact;
 import org.apache.maven.artifact.factory.ArtifactFactory;
 import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
@@ -52,6 +53,7 @@ import org.apache.maven.plugin.AbstractMojo;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugin.MojoFailureException;
 import org.apache.maven.plugin.descriptor.PluginDescriptor;
+import org.apache.maven.plugin.logging.Log;
 import org.apache.maven.plugin.surefire.booterclient.ChecksumCalculator;
 import org.apache.maven.plugin.surefire.booterclient.ForkConfiguration;
 import org.apache.maven.plugin.surefire.booterclient.ForkStarter;
@@ -436,14 +438,14 @@ public abstract class AbstractSurefireMojo
      * which is replaced with a fixed number for each of the parallel forks, ranging from <code>1</code> to the effective value of <code>forkCount</code>
      * times the maximum number of parallel Surefire executions in maven parallel builds, i.e. the effective value of the <code>-T</code> command line
      * argument of maven core.
-     * 
+     *
      * @since 2.14
      */
-    @Parameter( property = "forkCount", defaultValue="1")
+    @Parameter( property = "forkCount", defaultValue = "1" )
     private String forkCount;
 
     /**
-     * Indicates if forked VMs can be reused. If set to "false", a new VM is forked for each test class to be executed. 
+     * Indicates if forked VMs can be reused. If set to "false", a new VM is forked for each test class to be executed.
      * If set to "true", up to <code>forkCount</code> VMs will be forked and then reused to execute all tests.
      *
      * @since 2.13
@@ -588,7 +590,7 @@ public abstract class AbstractSurefireMojo
     private Toolchain toolchain;
 
     private int effectiveForkCount = -1;
-    
+
     /**
      * The placeholder that is replaced by the executing thread's running number. The thread number
      * range starts with 1
@@ -802,7 +804,8 @@ public abstract class AbstractSurefireMojo
             try
             {
                 ForkStarter forkStarter =
-                    createForkStarter( provider, forkConfiguration, classLoaderConfiguration, runOrderParameters );
+                    createForkStarter( provider, forkConfiguration, classLoaderConfiguration, runOrderParameters,
+                                       getLog() );
                 result = forkStarter.run( effectiveProperties, scanResult );
             }
             finally
@@ -1094,8 +1097,8 @@ public abstract class AbstractSurefireMojo
 
             final Classpath testClasspath = generateTestClasspath();
 
-            logClasspath( testClasspath, "test classpath" );
-            logClasspath( providerClasspath, "provider classpath" );
+            getLog().debug( testClasspath.getLogMessage( "test" ) );
+            getLog().debug( providerClasspath.getLogMessage( "provider" ) );
             final ClasspathConfiguration classpathConfiguration =
                 new ClasspathConfiguration( testClasspath, providerClasspath, inprocClassPath,
                                             effectiveIsEnableAssertions(), isChildDelegation() );
@@ -1131,24 +1134,6 @@ public abstract class AbstractSurefireMojo
                                                configChecksum, requiresRunHistory() );
     }
 
-    void logClasspath( Classpath classpath, String descriptor )
-    {
-        getLog().debug( descriptor + " classpath:" );
-        @SuppressWarnings( "unchecked" ) final List<String> classPath = classpath.getClassPath();
-        for ( String classpathElement : classPath )
-        {
-            if ( classpathElement == null )
-            {
-                getLog().warn( "The test classpath contains a null element." );
-            }
-            else
-            {
-                getLog().debug( "  " + classpathElement );
-            }
-        }
-    }
-
-
     private boolean isSpecificTestSpecified()
     {
         return getTest() != null;
@@ -1230,7 +1215,7 @@ public abstract class AbstractSurefireMojo
             // Have to wrap in an ArrayList as surefire expects an ArrayList instead of a List for some reason
             if ( excludes == null || excludes.size() == 0 )
             {
-                excludes = Arrays.asList( new String[]{ "**/*$*" } );
+                excludes = Arrays.asList( "**/*$*" );
             }
         }
         return filterNulls( excludes );
@@ -1371,7 +1356,7 @@ public abstract class AbstractSurefireMojo
 
     protected ForkStarter createForkStarter( ProviderInfo provider, ForkConfiguration forkConfiguration,
                                              ClassLoaderConfiguration classLoaderConfiguration,
-                                             RunOrderParameters runOrderParameters )
+                                             RunOrderParameters runOrderParameters, Log log )
         throws MojoExecutionException, MojoFailureException
     {
         StartupConfiguration startupConfiguration = createStartupConfiguration( provider, classLoaderConfiguration );
@@ -1379,7 +1364,7 @@ public abstract class AbstractSurefireMojo
         StartupReportConfiguration startupReportConfiguration = getStartupReportConfiguration( configChecksum );
         ProviderConfiguration providerConfiguration = createProviderConfiguration( runOrderParameters );
         return new ForkStarter( providerConfiguration, startupConfiguration, forkConfiguration,
-                                getForkedProcessTimeoutInSeconds(), startupReportConfiguration );
+                                getForkedProcessTimeoutInSeconds(), startupReportConfiguration, log );
     }
 
     protected InPluginVMSurefireStarter createInprocessStarter( ProviderInfo provider,
@@ -1419,19 +1404,22 @@ public abstract class AbstractSurefireMojo
         // FORK_ONCE (default) is represented by the default values of forkCount and reuseForks 
         if ( ForkConfiguration.FORK_PERTHREAD.equals( effectiveForkMode ) )
         {
-            forkCount = String.valueOf(threadCount);
+            forkCount = String.valueOf( threadCount );
         }
         else if ( ForkConfiguration.FORK_NEVER.equals( effectiveForkMode ) )
         {
             forkCount = "0";
-        } else if ( ForkConfiguration.FORK_ALWAYS.equals( effectiveForkMode )) {
+        }
+        else if ( ForkConfiguration.FORK_ALWAYS.equals( effectiveForkMode ) )
+        {
             forkCount = "1";
             reuseForks = false;
         }
 
-        if ( !ForkConfiguration.FORK_ONCE.equals( getForkMode() ) ) 
+        if ( !ForkConfiguration.FORK_ONCE.equals( getForkMode() ) )
         {
-            getLog().warn( "The parameter forkMode is deprecated since version 2.14. Use forkCount and reuseForks instead." );
+            getLog().warn(
+                "The parameter forkMode is deprecated since version 2.14. Use forkCount and reuseForks instead." );
         }
     }
 

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/aae5a8c9/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkConfiguration.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkConfiguration.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkConfiguration.java
index 15d76a3..8f6f3c9 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkConfiguration.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkConfiguration.java
@@ -27,13 +27,14 @@ import java.util.Map;
 import java.util.jar.JarEntry;
 import java.util.jar.JarOutputStream;
 import java.util.jar.Manifest;
+
 import org.apache.maven.plugin.surefire.AbstractSurefireMojo;
 import org.apache.maven.plugin.surefire.booterclient.lazytestprovider.OutputStreamFlushableCommandline;
 import org.apache.maven.plugin.surefire.util.Relocator;
 import org.apache.maven.shared.utils.StringUtils;
-import org.apache.maven.surefire.booter.ClassLoaderConfiguration;
 import org.apache.maven.surefire.booter.Classpath;
 import org.apache.maven.surefire.booter.ForkedBooter;
+import org.apache.maven.surefire.booter.StartupConfiguration;
 import org.apache.maven.surefire.booter.SurefireBooterForkException;
 import org.apache.maven.surefire.util.UrlUtils;
 
@@ -117,25 +118,26 @@ public class ForkConfiguration
     }
 
     /**
-     * @param classPath              cla the classpath arguments
-     * @param classpathConfiguration the classpath configuration
-     * @param shadefire              true if running shadefire
-     * @param threadNumber           the thread number, to be the replacement in the argLine
-     * @return A commandline
+     * @param classPath            cla the classpath arguments
+     * @param startupConfiguration
+     * @param threadNumber         the thread number, to be the replacement in the argLine   @return A commandline
      * @throws org.apache.maven.surefire.booter.SurefireBooterForkException
      *          when unable to perform the fork
      */
     public OutputStreamFlushableCommandline createCommandLine( List<String> classPath,
-                                                               ClassLoaderConfiguration classpathConfiguration,
-                                                               boolean shadefire, int threadNumber )
+                                                               StartupConfiguration startupConfiguration,
+                                                               int threadNumber )
         throws SurefireBooterForkException
     {
-        return createCommandLine( classPath, classpathConfiguration.isManifestOnlyJarRequestedAndUsable(), shadefire,
-                                  threadNumber );
+        return createCommandLine( classPath,
+                                  startupConfiguration.getClassLoaderConfiguration().isManifestOnlyJarRequestedAndUsable(),
+                                  startupConfiguration.isShadefire(), startupConfiguration.isProviderMainClass()
+            ? startupConfiguration.getActualClassName()
+            : ForkedBooter.class.getName(), threadNumber );
     }
 
-    public OutputStreamFlushableCommandline createCommandLine( List<String> classPath, boolean useJar,
-                                                               boolean shadefire, int threadNumber )
+    OutputStreamFlushableCommandline createCommandLine( List<String> classPath, boolean useJar, boolean shadefire,
+                                                        String providerThatHasMainMethod, int threadNumber )
         throws SurefireBooterForkException
     {
         OutputStreamFlushableCommandline cli = new OutputStreamFlushableCommandline();
@@ -168,7 +170,7 @@ public class ForkConfiguration
             File jarFile;
             try
             {
-                jarFile = createJar( classPath );
+                jarFile = createJar( classPath, providerThatHasMainMethod );
             }
             catch ( IOException e )
             {
@@ -183,7 +185,8 @@ public class ForkConfiguration
         {
             cli.addEnvironment( "CLASSPATH", StringUtils.join( classPath.iterator(), File.pathSeparator ) );
 
-            final String forkedBooter = ForkedBooter.class.getName();
+            final String forkedBooter =
+                providerThatHasMainMethod != null ? providerThatHasMainMethod : ForkedBooter.class.getName();
 
             cli.createArg().setValue( shadefire ? new Relocator().relocate( forkedBooter ) : forkedBooter );
         }
@@ -195,19 +198,21 @@ public class ForkConfiguration
 
     private String replaceThreadNumberPlaceholder( String argLine, int threadNumber )
     {
-        return argLine.replace( AbstractSurefireMojo.THREAD_NUMBER_PLACEHOLDER, String.valueOf( threadNumber ) )
-                        .replace( AbstractSurefireMojo.FORK_NUMBER_PLACEHOLDER, String.valueOf( threadNumber ) );
+        return argLine.replace( AbstractSurefireMojo.THREAD_NUMBER_PLACEHOLDER,
+                                String.valueOf( threadNumber ) ).replace( AbstractSurefireMojo.FORK_NUMBER_PLACEHOLDER,
+                                                                          String.valueOf( threadNumber ) );
     }
 
     /**
      * Create a jar with just a manifest containing a Main-Class entry for BooterConfiguration and a Class-Path entry
      * for all classpath elements.
      *
-     * @param classPath List&lt;String> of all classpath elements.
+     * @param classPath      List&lt;String> of all classpath elements.
+     * @param startClassName
      * @return The file pointint to the jar
      * @throws java.io.IOException When a file operation fails.
      */
-    public File createJar( List<String> classPath )
+    private File createJar( List<String> classPath, String startClassName )
         throws IOException
     {
         File file = File.createTempFile( "surefirebooter", ".jar", tempDirectory );
@@ -234,7 +239,7 @@ public class ForkConfiguration
 
         man.getMainAttributes().putValue( "Manifest-Version", "1.0" );
         man.getMainAttributes().putValue( "Class-Path", cp.trim() );
-        man.getMainAttributes().putValue( "Main-Class", ForkedBooter.class.getName() );
+        man.getMainAttributes().putValue( "Main-Class", startClassName );
 
         man.write( jos );
         jos.close();

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/aae5a8c9/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java
index 8dd43da..6203609 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java
@@ -37,6 +37,7 @@ import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 
+import org.apache.maven.plugin.logging.Log;
 import org.apache.maven.plugin.surefire.AbstractSurefireMojo;
 import org.apache.maven.plugin.surefire.CommonReflector;
 import org.apache.maven.plugin.surefire.StartupReportConfiguration;
@@ -71,7 +72,7 @@ import org.apache.maven.surefire.util.DefaultScanResult;
  * Lives only on the plugin-side (not present in remote vms)
  * <p/>
  * Knows how to fork new vms and also how to delegate non-forking invocation to SurefireStarter directly
- * 
+ *
  * @author Jason van Zyl
  * @author Emmanuel Venisse
  * @author Brett Porter
@@ -121,19 +122,22 @@ public class ForkStarter
 
     private final StartupReportConfiguration startupReportConfiguration;
 
+    private Log log;
+
     private final DefaultReporterFactory defaultReporterFactory;
 
     private static volatile int systemPropertiesFileCounter = 0;
 
     public ForkStarter( ProviderConfiguration providerConfiguration, StartupConfiguration startupConfiguration,
                         ForkConfiguration forkConfiguration, int forkedProcessTimeoutInSeconds,
-                        StartupReportConfiguration startupReportConfiguration )
+                        StartupReportConfiguration startupReportConfiguration, Log log )
     {
         this.forkConfiguration = forkConfiguration;
         this.providerConfiguration = providerConfiguration;
         this.forkedProcessTimeoutInSeconds = forkedProcessTimeoutInSeconds;
         this.startupConfiguration = startupConfiguration;
         this.startupReportConfiguration = startupReportConfiguration;
+        this.log = log;
         defaultReporterFactory = new DefaultReporterFactory( startupReportConfiguration );
     }
 
@@ -149,9 +153,8 @@ public class ForkStarter
             {
                 final ForkClient forkClient =
                     new ForkClient( defaultReporterFactory, startupReportConfiguration.getTestVmSystemProperties() );
-                result =
-                    fork( null, new PropertiesWrapper( providerProperties ), forkClient, effectiveSystemProperties,
-                          null );
+                result = fork( null, new PropertiesWrapper( providerProperties ), forkClient, effectiveSystemProperties,
+                               null );
             }
             else
             {
@@ -182,9 +185,8 @@ public class ForkStarter
     {
 
         ArrayList<Future<RunResult>> results = new ArrayList<Future<RunResult>>( forkCount );
-        ExecutorService executorService =
-            new ThreadPoolExecutor( forkCount, forkCount, 60, TimeUnit.SECONDS,
-                                    new ArrayBlockingQueue<Runnable>( forkCount ) );
+        ExecutorService executorService = new ThreadPoolExecutor( forkCount, forkCount, 60, TimeUnit.SECONDS,
+                                                                  new ArrayBlockingQueue<Runnable>( forkCount ) );
 
         try
         {
@@ -210,12 +212,12 @@ public class ForkStarter
                     public RunResult call()
                         throws Exception
                     {
-                        TestProvidingInputStream testProvidingInputStream = new TestProvidingInputStream( messageQueue );
+                        TestProvidingInputStream testProvidingInputStream =
+                            new TestProvidingInputStream( messageQueue );
 
-                        ForkClient forkClient =
-                            new ForkClient( defaultReporterFactory,
-                                            startupReportConfiguration.getTestVmSystemProperties(),
-                                            testProvidingInputStream );
+                        ForkClient forkClient = new ForkClient( defaultReporterFactory,
+                                                                startupReportConfiguration.getTestVmSystemProperties(),
+                                                                testProvidingInputStream );
 
                         return fork( null, new PropertiesWrapper( providerConfiguration.getProviderProperties() ),
                                      forkClient, effectiveSystemProperties, testProvidingInputStream );
@@ -279,9 +281,8 @@ public class ForkStarter
                     public RunResult call()
                         throws Exception
                     {
-                        ForkClient forkClient =
-                            new ForkClient( defaultReporterFactory,
-                                            startupReportConfiguration.getTestVmSystemProperties() );
+                        ForkClient forkClient = new ForkClient( defaultReporterFactory,
+                                                                startupReportConfiguration.getTestVmSystemProperties() );
                         return fork( testSet, new PropertiesWrapper( providerConfiguration.getProviderProperties() ),
                                      forkClient, effectiveSystemProperties, null );
                     }
@@ -373,11 +374,11 @@ public class ForkStarter
             if ( effectiveSystemProperties != null )
             {
                 SurefireProperties filteredProperties =
-                    AbstractSurefireMojo.createCopyAndReplaceForkNumPlaceholder( effectiveSystemProperties, forkNumber );
+                    AbstractSurefireMojo.createCopyAndReplaceForkNumPlaceholder( effectiveSystemProperties,
+                                                                                 forkNumber );
                 systPropsFile =
-                    SystemPropertyManager.writePropertiesFile( filteredProperties,
-                                                               forkConfiguration.getTempDirectory(), "surefire_"
-                                                                   + systemPropertiesFileCounter++,
+                    SystemPropertyManager.writePropertiesFile( filteredProperties, forkConfiguration.getTempDirectory(),
+                                                               "surefire_" + systemPropertiesFileCounter++,
                                                                forkConfiguration.isDebug() );
             }
         }
@@ -386,21 +387,24 @@ public class ForkStarter
             throw new SurefireBooterForkException( "Error creating properties files for forking", e );
         }
 
-        final Classpath bootClasspathConfiguration = forkConfiguration.getBootClasspath();
+        final Classpath bootClasspathConfiguration = startupConfiguration.isProviderMainClass()
+            ? startupConfiguration.getClasspathConfiguration().getProviderClasspath()
+            : forkConfiguration.getBootClasspath();
 
-        final Classpath additionlClassPathUrls =
-            startupConfiguration.useSystemClassLoader() ? startupConfiguration.getClasspathConfiguration().getTestClasspath()
-                            : null;
+        final Classpath additionlClassPathUrls = startupConfiguration.useSystemClassLoader()
+            ? startupConfiguration.getClasspathConfiguration().getTestClasspath()
+            : null;
 
         // Surefire-booter + all test classes if "useSystemClassloader"
         // Surefire-booter if !useSystemClassLoader
         Classpath bootClasspath = Classpath.join( bootClasspathConfiguration, additionlClassPathUrls );
 
-        @SuppressWarnings( "unchecked" )
+        if ( log.isDebugEnabled() )
+        {
+            log.debug( bootClasspath.getLogMessage( "boot" ) );
+        }
         OutputStreamFlushableCommandline cli =
-            forkConfiguration.createCommandLine( bootClasspath.getClassPath(),
-                                                 startupConfiguration.getClassLoaderConfiguration(),
-                                                 startupConfiguration.isShadefire(), forkNumber );
+            forkConfiguration.createCommandLine( bootClasspath.getClassPath(), startupConfiguration, forkNumber );
 
         final InputStreamCloser inputStreamCloser;
         final Thread inputStreamCloserHook;
@@ -472,15 +476,15 @@ public class ForkStarter
                 if ( errorInFork != null )
                 {
                     // noinspection ThrowFromFinallyBlock
-                    throw new RuntimeException( "There was an error in the forked process\n"
-                        + errorInFork.writeTraceToString() );
+                    throw new RuntimeException(
+                        "There was an error in the forked process\n" + errorInFork.writeTraceToString() );
                 }
                 if ( !forkClient.isSaidGoodBye() )
                 {
                     // noinspection ThrowFromFinallyBlock
                     throw new RuntimeException(
-                                                "The forked VM terminated without saying properly goodbye. VM crash or System.exit called ?"
-                                                    + "\nCommand was" + cli.toString() );
+                        "The forked VM terminated without saying properly goodbye. VM crash or System.exit called ?"
+                            + "\nCommand was" + cli.toString() );
                 }
 
             }
@@ -498,14 +502,15 @@ public class ForkStarter
         {
             final ClasspathConfiguration classpathConfiguration = startupConfiguration.getClasspathConfiguration();
             ClassLoader testsClassLoader = classpathConfiguration.createTestClassLoader( false );
-            ClassLoader surefireClassLoader = classpathConfiguration.createInprocSurefireClassLoader( testsClassLoader );
+            ClassLoader surefireClassLoader =
+                classpathConfiguration.createInprocSurefireClassLoader( testsClassLoader );
 
             CommonReflector commonReflector = new CommonReflector( surefireClassLoader );
             Object reporterFactory = commonReflector.createReportingReporterFactory( startupReportConfiguration );
 
             final ProviderFactory providerFactory =
-                new ProviderFactory( startupConfiguration, providerConfiguration, surefireClassLoader,
-                                     testsClassLoader, reporterFactory );
+                new ProviderFactory( startupConfiguration, providerConfiguration, surefireClassLoader, testsClassLoader,
+                                     reporterFactory );
             SurefireProvider surefireProvider = providerFactory.createProvider( false );
             return surefireProvider.getSuites();
         }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/aae5a8c9/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkConfigurationTest.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkConfigurationTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkConfigurationTest.java
index b272aac..c37b9f2 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkConfigurationTest.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkConfigurationTest.java
@@ -22,6 +22,7 @@ package org.apache.maven.plugin.surefire.booterclient;
 import java.io.File;
 import java.io.IOException;
 import java.util.Collections;
+
 import org.apache.maven.shared.utils.StringUtils;
 import org.apache.maven.shared.utils.cli.Commandline;
 import org.apache.maven.surefire.booter.Classpath;
@@ -40,7 +41,7 @@ public class ForkConfigurationTest
         File cpElement = getTempClasspathFile();
 
         Commandline cli =
-            config.createCommandLine( Collections.singletonList( cpElement.getAbsolutePath() ), true, false, 1 );
+            config.createCommandLine( Collections.singletonList( cpElement.getAbsolutePath() ), true, false, null, 1 );
 
         String line = StringUtils.join( cli.getCommandline(), " " );
         assertTrue( line.contains( "-jar" ) );
@@ -55,7 +56,7 @@ public class ForkConfigurationTest
 
         final Commandline commandLine =
             forkConfiguration.createCommandLine( Collections.singletonList( cpElement.getAbsolutePath() ), false, false,
-                                                 1 );
+                                                 null, 1 );
         assertTrue( commandLine.toString().contains( "abc def" ) );
     }
 
@@ -70,8 +71,8 @@ public class ForkConfigurationTest
     public static ForkConfiguration getForkConfiguration( String argLine, String jvm )
         throws IOException
     {
-        return new ForkConfiguration( new Classpath(), null, null, jvm, new File( "." ).getCanonicalFile(), argLine, null,
-                               false, 1, false );
+        return new ForkConfiguration( new Classpath(), null, null, jvm, new File( "." ).getCanonicalFile(), argLine,
+                                      null, false, 1, false );
     }
 
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/aae5a8c9/surefire-booter/src/main/java/org/apache/maven/surefire/booter/Classpath.java
----------------------------------------------------------------------
diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/Classpath.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/Classpath.java
index fe71855..818b2e5 100644
--- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/Classpath.java
+++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/Classpath.java
@@ -26,6 +26,7 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
+
 import org.apache.maven.surefire.util.UrlUtils;
 
 /**
@@ -168,4 +169,16 @@ public class Classpath
     {
         return elements != null ? elements.hashCode() : 0;
     }
+
+    public String getLogMessage( String descriptor )
+    {
+        StringBuffer result = new StringBuffer();
+        result.append( descriptor ).append( " classpath:" );
+        int size = elements.size();
+        for ( int i = 0; i < size; i++ )
+        {
+            result.append( "  " ).append( (String) elements.get( i ) );
+        }
+        return result.toString();
+    }
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/aae5a8c9/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ClasspathConfiguration.java
----------------------------------------------------------------------
diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ClasspathConfiguration.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ClasspathConfiguration.java
index e3b8243..8ae4ec7 100644
--- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ClasspathConfiguration.java
+++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ClasspathConfiguration.java
@@ -102,6 +102,11 @@ public class ClasspathConfiguration
         return surefireClasspathUrls.createClassLoader( parent, false, enableAssertions, "provider" );
     }
 
+    public Classpath getProviderClasspath()
+    {
+        return surefireClasspathUrls;
+    }
+
     public ClassLoader createInprocSurefireClassLoader( ClassLoader parent )
         throws SurefireExecutionException
     {

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/aae5a8c9/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderFactory.java
----------------------------------------------------------------------
diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderFactory.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderFactory.java
index a21da57..021d04b 100644
--- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderFactory.java
+++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderFactory.java
@@ -23,6 +23,7 @@ import java.io.PrintStream;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.Iterator;
+
 import org.apache.maven.surefire.providerapi.SurefireProvider;
 import org.apache.maven.surefire.report.ReporterException;
 import org.apache.maven.surefire.suite.RunResult;
@@ -112,7 +113,7 @@ public class ProviderFactory
         surefireReflector.setRunOrderParameters( o, providerConfiguration.getRunOrderParameters() );
         surefireReflector.setIfDirScannerAware( o, providerConfiguration.getDirScannerParams() );
 
-        Object provider = surefireReflector.instantiateProvider( starterConfiguration.getProviderClassName(), o );
+        Object provider = surefireReflector.instantiateProvider( starterConfiguration.getActualClassName(), o );
         Thread.currentThread().setContextClassLoader( systemClassLoader );
 
         return new ProviderProxy( provider, testsClassLoader );

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/aae5a8c9/surefire-booter/src/main/java/org/apache/maven/surefire/booter/StartupConfiguration.java
----------------------------------------------------------------------
diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/StartupConfiguration.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/StartupConfiguration.java
index 32d3f79..1c454db 100644
--- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/StartupConfiguration.java
+++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/StartupConfiguration.java
@@ -43,13 +43,18 @@ public class StartupConfiguration
                                  ClassLoaderConfiguration classLoaderConfiguration, boolean isForkRequested,
                                  boolean inForkedVm )
     {
-        this.providerClassName = providerClassName;
         this.classpathConfiguration = classpathConfiguration;
         this.classLoaderConfiguration = classLoaderConfiguration;
         this.isForkRequested = isForkRequested;
+        this.providerClassName = providerClassName;
         isInForkedVm = inForkedVm;
     }
 
+    public boolean isProviderMainClass()
+    {
+        return providerClassName.endsWith( "#main" );
+    }
+
     public static StartupConfiguration inForkedVm( String providerClassName,
                                                    ClasspathConfiguration classpathConfiguration,
                                                    ClassLoaderConfiguration classLoaderConfiguration )
@@ -79,6 +84,50 @@ public class StartupConfiguration
         return providerClassName;
     }
 
+    public String getActualClassName()
+    {
+        if ( isProviderMainClass() )
+        {
+            return stripEnd( providerClassName, "#main" );
+        }
+        return providerClassName;
+    }
+
+    /**
+     * <p>Strip any of a supplied String from the end of a String.</p>
+     * <p/>
+     * <p>If the strip String is <code>null</code>, whitespace is
+     * stripped.</p>
+     *
+     * @param str   the String to remove characters from
+     * @param strip the String to remove
+     * @return the stripped String
+     */
+    public static String stripEnd( String str, String strip )
+    {
+        if ( str == null )
+        {
+            return null;
+        }
+        int end = str.length();
+
+        if ( strip == null )
+        {
+            while ( ( end != 0 ) && Character.isWhitespace( str.charAt( end - 1 ) ) )
+            {
+                end--;
+            }
+        }
+        else
+        {
+            while ( ( end != 0 ) && ( strip.indexOf( str.charAt( end - 1 ) ) != -1 ) )
+            {
+                end--;
+            }
+        }
+        return str.substring( 0, end );
+    }
+
     public ClassLoaderConfiguration getClassLoaderConfiguration()
     {
         return classLoaderConfiguration;

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/aae5a8c9/surefire-shadefire/pom.xml
----------------------------------------------------------------------
diff --git a/surefire-shadefire/pom.xml b/surefire-shadefire/pom.xml
index fcdeb04..f840279 100644
--- a/surefire-shadefire/pom.xml
+++ b/surefire-shadefire/pom.xml
@@ -17,7 +17,8 @@
   ~ under the License.
   -->
 
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
 
   <parent>
@@ -47,7 +48,6 @@
       <groupId>org.apache.maven.surefire</groupId>
       <artifactId>surefire-junit3</artifactId>
       <version>${shadedVersion}</version>
-      <scope>provided</scope>
     </dependency>
     <dependency>
       <groupId>org.apache.maven.surefire</groupId>