You are viewing a plain text version of this content. The canonical link for it is here.
Posted to surefire-commits@maven.apache.org by kr...@apache.org on 2010/12/04 23:16:47 UTC

svn commit: r1042246 [1/2] - in /maven/surefire/trunk: maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/ maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ maven-surefire-common/src/main/java/org/apache/maven/plug...

Author: krosenvold
Date: Sat Dec  4 22:16:45 2010
New Revision: 1042246

URL: http://svn.apache.org/viewvc?rev=1042246&view=rev
Log:
[SUREFIRE-408] Made it possible to explicitly specify provider

ServiceProvider code by Stephen Connolly

Added:
    maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireDependencyResolver.java   (with props)
    maven/surefire/trunk/maven-surefire-plugin/src/site/apt/examples/providers.apt.vm   (with props)
    maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/booter/ProviderDetector.java   (with props)
    maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/BooterParameters.java   (with props)
    maven/surefire/trunk/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/Surefire408ManualProviderSelectionIT.java   (with props)
    maven/surefire/trunk/surefire-integration-tests/src/test/resources/surefire-408-manual-provider-selection/
    maven/surefire/trunk/surefire-integration-tests/src/test/resources/surefire-408-manual-provider-selection/pom.xml   (with props)
    maven/surefire/trunk/surefire-integration-tests/src/test/resources/surefire-408-manual-provider-selection/src/
    maven/surefire/trunk/surefire-integration-tests/src/test/resources/surefire-408-manual-provider-selection/src/test/
    maven/surefire/trunk/surefire-integration-tests/src/test/resources/surefire-408-manual-provider-selection/src/test/java/
    maven/surefire/trunk/surefire-integration-tests/src/test/resources/surefire-408-manual-provider-selection/src/test/java/junit/
    maven/surefire/trunk/surefire-integration-tests/src/test/resources/surefire-408-manual-provider-selection/src/test/java/junit/twoTestCases/
    maven/surefire/trunk/surefire-integration-tests/src/test/resources/surefire-408-manual-provider-selection/src/test/java/junit/twoTestCases/BasicTest.java   (with props)
    maven/surefire/trunk/surefire-integration-tests/src/test/resources/surefire-408-manual-provider-selection/src/test/java/junit/twoTestCases/TestTwo.java   (with props)
    maven/surefire/trunk/surefire-providers/surefire-junit/src/main/resources/
    maven/surefire/trunk/surefire-providers/surefire-junit/src/main/resources/META-INF/
    maven/surefire/trunk/surefire-providers/surefire-junit/src/main/resources/META-INF/services/
    maven/surefire/trunk/surefire-providers/surefire-junit/src/main/resources/META-INF/services/org.apache.maven.surefire.providerapi.SurefireProvider
    maven/surefire/trunk/surefire-providers/surefire-junit4/src/main/resources/
    maven/surefire/trunk/surefire-providers/surefire-junit4/src/main/resources/META-INF/
    maven/surefire/trunk/surefire-providers/surefire-junit4/src/main/resources/META-INF/services/
    maven/surefire/trunk/surefire-providers/surefire-junit4/src/main/resources/META-INF/services/org.apache.maven.surefire.providerapi.SurefireProvider
    maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/resources/
    maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/resources/META-INF/
    maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/resources/META-INF/services/
    maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/resources/META-INF/services/org.apache.maven.surefire.providerapi.SurefireProvider
    maven/surefire/trunk/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/SpiTest.java   (with props)
    maven/surefire/trunk/surefire-providers/surefire-testng/src/main/resources/
    maven/surefire/trunk/surefire-providers/surefire-testng/src/main/resources/META-INF/
    maven/surefire/trunk/surefire-providers/surefire-testng/src/main/resources/META-INF/services/
    maven/surefire/trunk/surefire-providers/surefire-testng/src/main/resources/META-INF/services/org.apache.maven.surefire.providerapi.SurefireProvider
Removed:
    maven/surefire/trunk/surefire-providers/surefire-junit/src/main/java/org/apache/maven/surefire/junit/JUnit3ProviderFactory.java
    maven/surefire/trunk/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4ProviderFactory.java
    maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProviderFactory.java
    maven/surefire/trunk/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProviderFactory.java
Modified:
    maven/surefire/trunk/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
    maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
    maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java
    maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkConfiguration.java
    maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java
    maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerTest.java
    maven/surefire/trunk/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
    maven/surefire/trunk/maven-surefire-plugin/src/site/site.xml
    maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java
    maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/BaseProviderFactory.java
    maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/SurefireProvider.java
    maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderConfiguration.java
    maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderFactory.java
    maven/surefire/trunk/surefire-integration-tests/pom.xml
    maven/surefire/trunk/surefire-providers/surefire-junit/pom.xml
    maven/surefire/trunk/surefire-providers/surefire-junit/src/main/java/org/apache/maven/surefire/junit/JUnit3Provider.java
    maven/surefire/trunk/surefire-providers/surefire-junit4/pom.xml
    maven/surefire/trunk/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java
    maven/surefire/trunk/surefire-providers/surefire-junit47/pom.xml
    maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreParameters.java
    maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java
    maven/surefire/trunk/surefire-providers/surefire-testng/pom.xml
    maven/surefire/trunk/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java

Modified: maven/surefire/trunk/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java?rev=1042246&r1=1042245&r2=1042246&view=diff
==============================================================================
--- maven/surefire/trunk/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java (original)
+++ maven/surefire/trunk/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java Sat Dec  4 22:16:45 2010
@@ -601,12 +601,13 @@ public class IntegrationTestMojo
     public void execute()
         throws MojoExecutionException, MojoFailureException
     {
+        final AbstractSurefireMojo.WellKnownProvider provider = initialize();
         if ( verifyParameters() )
         {
             final Classpath bootClasspathConfiguration = new Classpath();
             ForkConfiguration forkConfiguration = getForkConfiguration( bootClasspathConfiguration );
 
-            BooterConfiguration booterConfiguration = createBooterConfiguration( forkConfiguration );
+            BooterConfiguration booterConfiguration = createBooterConfiguration( forkConfiguration, provider );
             ForkStarter booter = new ForkStarter( booterConfiguration, reportsDirectory, forkConfiguration );
 
             getLog().info(

Modified: maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java?rev=1042246&r1=1042245&r2=1042246&view=diff
==============================================================================
--- maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java (original)
+++ maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java Sat Dec  4 22:16:45 2010
@@ -29,7 +29,6 @@ import org.apache.maven.artifact.resolve
 import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
 import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
 import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
-import org.apache.maven.artifact.versioning.OverConstrainedVersionException;
 import org.apache.maven.artifact.versioning.VersionRange;
 import org.apache.maven.plugin.AbstractMojo;
 import org.apache.maven.plugin.MojoExecutionException;
@@ -40,6 +39,8 @@ import org.apache.maven.surefire.booter.
 import org.apache.maven.surefire.booter.Classpath;
 import org.apache.maven.surefire.booter.ClasspathConfiguration;
 import org.apache.maven.surefire.booter.ProviderConfiguration;
+import org.apache.maven.surefire.booter.ProviderDetector;
+import org.apache.maven.surefire.providerapi.SurefireProvider;
 import org.apache.maven.surefire.report.BriefConsoleReporter;
 import org.apache.maven.surefire.report.BriefFileReporter;
 import org.apache.maven.surefire.report.ConsoleReporter;
@@ -55,6 +56,7 @@ import org.apache.maven.toolchain.Toolch
 import org.codehaus.plexus.util.StringUtils;
 
 import java.io.File;
+import java.io.IOException;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -87,9 +89,84 @@ public abstract class AbstractSurefireMo
 
     protected abstract String getPluginName();
 
+    protected SurefireDependencyResolver dependencyResolver;
+
     protected abstract boolean verifyParameters()
         throws MojoFailureException;
 
+    private Artifact surefireArtifact;
+
+
+    WellKnownProvider[] wellKnownProviders;
+
+    protected WellKnownProvider initialize()
+        throws MojoFailureException
+    {
+        dependencyResolver =
+            new SurefireDependencyResolver( getArtifactResolver(), getArtifactFactory(), getLog(), getLocalRepository(),
+                                            getRemoteRepositories(), getMetadataSource(), getPluginName() );
+
+        try
+        {
+            wellKnownProviders = new WellKnownProvider[]{ new TestNgProviderInfo( getTestNgArtifact() ),
+                new JUnitCoreProviderInfo( getJunitArtifact() ), new JUnit4ProviderInfo( getJunitArtifact() ),
+                new JUnit3ProviderInfo() };
+            String manuallyConfiguredProvider = getManuallyConfiguredProviderName();
+            if ( manuallyConfiguredProvider != null )
+            {
+                // Ok, all this code will have to go when we solve surefire-141. In the meantime we solve surefire-408
+                for ( int i = 0; i < wellKnownProviders.length; i++ )
+                {
+                    WellKnownProvider wellKnownProvider = wellKnownProviders[i];
+                    if ( wellKnownProvider.getProviderName().equals( manuallyConfiguredProvider ) )
+                    {
+                        getLog().info( "Using explicitly configured provider " + wellKnownProvider.getProviderName() );
+                        return wellKnownProvider;
+                    }
+                }
+                throw new IllegalArgumentException( "Unknown provider configured " + manuallyConfiguredProvider );
+            }
+            for ( int i = 0; i < wellKnownProviders.length; i++ )
+            {
+                if ( wellKnownProviders[i].isApplicable() )
+                {
+                    return wellKnownProviders[i];
+                }
+            }
+            return null;
+        }
+        catch ( InvalidVersionSpecificationException e )
+        {
+            throw new RuntimeException( e );
+        }
+    }
+
+    private String getManuallyConfiguredProviderName()
+    {
+        try
+        {
+            final Set objects = ProviderDetector.getServiceNames( SurefireProvider.class,
+                                                                  Thread.currentThread().getContextClassLoader() );
+            if ( objects == null || objects.size() == 0 )
+            {
+                return null;
+            }
+            if ( objects.size() > 1 )
+            {
+                throw new IllegalArgumentException( "Surefire currently only supports " );
+            }
+            return (String) objects.iterator().next();
+
+        }
+
+        catch ( IOException e )
+        {
+            throw new RuntimeException( e );
+        }
+
+
+    }
+
     protected final Toolchain getToolchain()
     {
         Toolchain tc = null;
@@ -134,6 +211,12 @@ public abstract class AbstractSurefireMo
         {
             getProperties().setProperty( "objectfactory", this.getObjectFactory() );
         }
+        if ( this.getTestClassesDirectory() != null )
+        {
+            getProperties().setProperty( "testng.test.classpath", getTestClassesDirectory().getAbsolutePath() );
+        }
+
+
     }
 
     protected boolean isAnyConcurrencySelected()
@@ -168,52 +251,16 @@ public abstract class AbstractSurefireMo
         {
             getProperties().setProperty( "useUnlimitedThreads", getUseUnlimitedThreads() );
         }
-        Artifact configurableParallelComputer =
-            (Artifact) getProjectArtifactMap().get( "org.jdogma.junit:configurable-parallel-computer" );
-        getProperties().setProperty( "configurableParallelComputerPresent",
-                                     Boolean.toString( configurableParallelComputer != null ) );
-
     }
 
     private boolean isJunit47Compatible( Artifact artifact )
-        throws MojoExecutionException
     {
-        return isWithinVersionSpec( artifact, "[4.7,)" );
+        return dependencyResolver.isWithinVersionSpec( artifact, "[4.7,)" );
     }
 
     private boolean isAnyJunit4( Artifact artifact )
-        throws MojoExecutionException
     {
-        return isWithinVersionSpec( artifact, "[4.0,)" );
-    }
-
-    private boolean isWithinVersionSpec( Artifact artifact, String versionSpec )
-        throws MojoExecutionException
-    {
-        if ( artifact == null )
-        {
-            return false;
-        }
-        try
-        {
-            VersionRange range = VersionRange.createFromVersionSpec( versionSpec );
-            try
-            {
-                return range.containsVersion( artifact.getSelectedVersion() );
-            }
-            catch ( NullPointerException e )
-            {
-                return range.containsVersion( new DefaultArtifactVersion( artifact.getBaseVersion() ) );
-            }
-        }
-        catch ( InvalidVersionSpecificationException e )
-        {
-            throw new MojoExecutionException( "Bug in junit 4.7 plugin. Please report with stacktrace" );
-        }
-        catch ( OverConstrainedVersionException e )
-        {
-            throw new MojoExecutionException( "Bug in junit 4.7 plugin. Please report with stacktrace" );
-        }
+        return dependencyResolver.isWithinVersionSpec( artifact, "[4.0,)" );
     }
 
     protected boolean isForkModeNever()
@@ -221,7 +268,8 @@ public abstract class AbstractSurefireMo
         return ForkConfiguration.FORK_NEVER.equals( getForkMode() );
     }
 
-    protected BooterConfiguration createBooterConfiguration( ForkConfiguration forkConfiguration )
+    protected BooterConfiguration createBooterConfiguration( ForkConfiguration forkConfiguration,
+                                                             WellKnownProvider provider )
         throws MojoExecutionException, MojoFailureException
     {
         final ClasspathConfiguration classpathConfiguration =
@@ -231,8 +279,7 @@ public abstract class AbstractSurefireMo
         ReporterConfiguration reporterConfiguration =
             new ReporterConfiguration( reports, getReportsDirectory(), Boolean.valueOf( isTrimStackTrace() ) );
 
-        Artifact surefireArtifact =
-            (Artifact) getPluginArtifactMap().get( "org.apache.maven.surefire:surefire-booter" );
+        surefireArtifact = (Artifact) getPluginArtifactMap().get( "org.apache.maven.surefire:surefire-booter" );
         if ( surefireArtifact == null )
         {
             throw new MojoExecutionException( "Unable to locate surefire-booter in the list of plugin artifacts" );
@@ -242,18 +289,19 @@ public abstract class AbstractSurefireMo
 
         Artifact junitArtifact;
         Artifact testNgArtifact;
-        String providerFactoryName;
+        String providerName;
         try
         {
-            addArtifact( forkConfiguration.getBootClasspathConfiguration(), surefireArtifact );
+            addArtifact( forkConfiguration.getBootClasspath(), surefireArtifact );
 
             junitArtifact = getJunitArtifact();
 
             testNgArtifact = getTestNgArtifact();
 
-            providerFactoryName =
-                setCorrectProvider( forkConfiguration.getBootClasspathConfiguration(), classpathConfiguration,
-                                    surefireArtifact, junitArtifact, testNgArtifact );
+            provider.addProviderProperties();
+            provider.addProviderArtifactToBootClasspath( forkConfiguration.getBootClasspath() );
+            provider.addProviderArtifactToSurefireClasspath( classpathConfiguration );
+            providerName = provider.getProviderName();
         }
         catch ( ArtifactNotFoundException e )
         {
@@ -273,8 +321,7 @@ public abstract class AbstractSurefireMo
         final boolean isTestNg = testNgArtifact != null;
         TestArtifactInfo testNg =
             isTestNg ? new TestArtifactInfo( testNgArtifact.getVersion(), testNgArtifact.getClassifier() ) : null;
-        TestRequest testSuiteDefinition =
-            new TestRequest( getSuiteXmlFiles(), getTestSourceDirectory(), getTest() );
+        TestRequest testSuiteDefinition = new TestRequest( getSuiteXmlFiles(), getTestSourceDirectory(), getTest() );
         final boolean failIfNoTests;
 
         if ( isValidSuiteXmlFileConfig() && getTest() == null )
@@ -311,7 +358,7 @@ public abstract class AbstractSurefireMo
             providerProperties = new Properties();
         }
         ProviderConfiguration surefireStarterConfiguration =
-            new ProviderConfiguration( providerFactoryName, classpathConfiguration,
+            new ProviderConfiguration( providerName, classpathConfiguration,
                                        forkConfiguration.getClassLoaderConfiguration(), forkConfiguration.isForking(),
                                        false, isRedirectTestOutputToFile() );
 
@@ -438,58 +485,6 @@ public abstract class AbstractSurefireMo
         return includes;
     }
 
-    private String setCorrectProvider( Classpath bootClasspathConfiguration,
-                                       ClasspathConfiguration classpathConfiguration, Artifact surefireArtifact,
-                                       Artifact junitArtifact, Artifact testNgArtifact )
-        throws ArtifactNotFoundException, ArtifactResolutionException, MojoExecutionException
-    {
-        if ( testNgArtifact != null )
-        {
-            setTestNgProvider( bootClasspathConfiguration, classpathConfiguration, surefireArtifact, testNgArtifact );
-            return "org.apache.maven.surefire.testng.TestNGProviderFactory";
-
-        }
-        else if ( junitArtifact != null && isAnyJunit4( junitArtifact ) )
-        {
-            if ( isAnyConcurrencySelected() && isJunit47Compatible( junitArtifact ) )
-            {
-                convertJunitCoreParameters();
-                setProvider( classpathConfiguration, "surefire-junit47", surefireArtifact.getBaseVersion(), null );
-                return "org.apache.maven.surefire.junitcore.JUnitCoreProviderFactory";
-            }
-            else
-            {
-                setProvider( classpathConfiguration, "surefire-junit4", surefireArtifact.getBaseVersion(), null );
-                return "org.apache.maven.surefire.junit4.JUnit4ProviderFactory";
-            }
-        }
-        else
-        {
-            // add the JUnit provider as default - it doesn't require JUnit to be present,
-            // since it supports POJO tests.
-            setProvider( classpathConfiguration, "surefire-junit", surefireArtifact.getBaseVersion(), null );
-            return "org.apache.maven.surefire.junit.JUnit3ProviderFactory";
-        }
-    }
-
-    private void setTestNgProvider( Classpath bootClasspathConfiguration, ClasspathConfiguration classpathConfiguration,
-                                    Artifact surefireArtifact, Artifact testNgArtifact )
-        throws ArtifactNotFoundException, ArtifactResolutionException
-    {
-        convertTestNGParameters();
-
-        if ( this.getTestClassesDirectory() != null )
-        {
-            getProperties().setProperty( "testng.test.classpath", getTestClassesDirectory().getAbsolutePath() );
-        }
-
-        addArtifact( bootClasspathConfiguration, testNgArtifact );
-
-        // The plugin uses a JDK based profile to select the right testng. We might be explicity using a
-        // different one since its based on the source level, not the JVM. Prune using the filter.
-        setProvider( classpathConfiguration, "surefire-testng", surefireArtifact.getBaseVersion(), testNgArtifact );
-    }
-
     private Artifact getTestNgArtifact()
         throws MojoFailureException, InvalidVersionSpecificationException
     {
@@ -691,28 +686,6 @@ public abstract class AbstractSurefireMo
     }
 
 
-    private void setProvider( ClasspathConfiguration classpathConfiguration, String provider, String version,
-                              Artifact filteredArtifact )
-        throws ArtifactNotFoundException, ArtifactResolutionException
-    {
-        Artifact providerArtifact =
-            getArtifactFactory().createDependencyArtifact( "org.apache.maven.surefire", provider,
-                                                           VersionRange.createFromVersion( version ), "jar", null,
-                                                           Artifact.SCOPE_TEST );
-        ArtifactResolutionResult result = resolveArtifact( filteredArtifact, providerArtifact );
-
-        for ( Iterator i = result.getArtifacts().iterator(); i.hasNext(); )
-        {
-            Artifact artifact = (Artifact) i.next();
-
-            getLog().debug(
-                "Adding to " + getPluginName() + " test classpath: " + artifact.getFile().getAbsolutePath() +
-                    " Scope: " + artifact.getScope() );
-
-            classpathConfiguration.addSurefireClasspathUrl( artifact.getFile().getAbsolutePath() );
-        }
-    }
-
     private ArtifactResolutionResult resolveArtifact( Artifact filteredArtifact, Artifact providerArtifact )
         throws ArtifactResolutionException, ArtifactNotFoundException
     {
@@ -927,4 +900,193 @@ public abstract class AbstractSurefireMo
             getLog().warn( "useSystemClassloader setting has no effect when not forking" );
         }
     }
+
+
+    public interface WellKnownProvider
+    {
+        String getProviderName();
+
+        String getProviderArtifactName();
+
+        public boolean isApplicable();
+
+        public void addProviderArtifactToBootClasspath( Classpath bootclasspath )
+            throws ArtifactResolutionException, ArtifactNotFoundException;
+
+        public void addProviderArtifactToSurefireClasspath( ClasspathConfiguration bootclasspath )
+            throws ArtifactResolutionException, ArtifactNotFoundException;
+
+        public void addProviderProperties();
+    }
+
+    class TestNgProviderInfo
+        implements WellKnownProvider
+    {
+        private final Artifact testNgArtifact;
+
+        TestNgProviderInfo( Artifact testNgArtifact )
+        {
+            this.testNgArtifact = testNgArtifact;
+        }
+
+        public String getProviderName()
+        {
+            return "org.apache.maven.surefire.testng.TestNGProvider";
+        }
+
+        public String getProviderArtifactName()
+        {
+            return "surefire-testng";
+        }
+
+        public boolean isApplicable()
+        {
+            return testNgArtifact != null;
+        }
+
+        public void addProviderProperties()
+        {
+            convertTestNGParameters();
+        }
+
+        public void addProviderArtifactToBootClasspath( Classpath bootclasspath )
+            throws ArtifactResolutionException, ArtifactNotFoundException
+        {
+
+            dependencyResolver.addResolvedArtifactToClasspath( bootclasspath, testNgArtifact );
+        }
+
+        public void addProviderArtifactToSurefireClasspath( ClasspathConfiguration bootclasspath )
+            throws ArtifactResolutionException, ArtifactNotFoundException
+        {
+            Artifact surefireArtifact =
+                (Artifact) getPluginArtifactMap().get( "org.apache.maven.surefire:surefire-booter" );
+            dependencyResolver.addProviderToClasspath( bootclasspath, "surefire-testng",
+                                                       surefireArtifact.getBaseVersion(), testNgArtifact );
+        }
+    }
+
+    class JUnit3ProviderInfo
+        implements WellKnownProvider
+    {
+        public String getProviderName()
+        {
+            return "org.apache.maven.surefire.junit.JUnit3Provider";
+        }
+
+        public String getProviderArtifactName()
+        {
+            return "surefire-junit3";
+        }
+
+        public boolean isApplicable()
+        {
+            return true;
+        }
+
+        public void addProviderProperties()
+        {
+        }
+
+        public void addProviderArtifactToBootClasspath( Classpath bootclasspath )
+        {
+        }
+
+        public void addProviderArtifactToSurefireClasspath( ClasspathConfiguration classpathConfiguration )
+            throws ArtifactResolutionException, ArtifactNotFoundException
+        {
+            // add the JUnit provider as default - it doesn't require JUnit to be present,
+            // since it supports POJO tests.
+            dependencyResolver.addProviderToClasspath( classpathConfiguration, getProviderArtifactName(),
+                                                       surefireArtifact.getBaseVersion(), null );
+
+        }
+
+    }
+
+    class JUnit4ProviderInfo
+        implements WellKnownProvider
+    {
+        private final Artifact junitArtifact;
+
+        JUnit4ProviderInfo( Artifact junitArtifact )
+        {
+            this.junitArtifact = junitArtifact;
+        }
+
+        public String getProviderName()
+        {
+            return "org.apache.maven.surefire.junit4.JUnit4Provider";
+        }
+
+        public String getProviderArtifactName()
+        {
+            return "surefire-junit4";
+        }
+
+        public boolean isApplicable()
+        {
+            return isAnyJunit4( junitArtifact );
+        }
+
+        public void addProviderProperties()
+        {
+        }
+
+        public void addProviderArtifactToBootClasspath( Classpath bootclasspath )
+        {
+        }
+
+        public void addProviderArtifactToSurefireClasspath( ClasspathConfiguration classpathConfiguration )
+            throws ArtifactResolutionException, ArtifactNotFoundException
+        {
+            dependencyResolver.addProviderToClasspath( classpathConfiguration, getProviderArtifactName(),
+                                                       surefireArtifact.getBaseVersion(), null );
+
+        }
+
+    }
+
+    class JUnitCoreProviderInfo
+        implements WellKnownProvider
+    {
+        private final Artifact junitArtifact;
+
+        JUnitCoreProviderInfo( Artifact junitArtifact )
+        {
+            this.junitArtifact = junitArtifact;
+        }
+
+        public String getProviderName()
+        {
+            return "org.apache.maven.surefire.junitcore.JUnitCoreProvider";
+        }
+
+        public String getProviderArtifactName()
+        {
+            return "surefire-junit47";
+        }
+
+        public boolean isApplicable()
+        {
+            return isAnyJunit4( junitArtifact ) && isAnyConcurrencySelected() && isJunit47Compatible( junitArtifact );
+        }
+
+        public void addProviderProperties()
+        {
+            convertJunitCoreParameters();
+        }
+
+        public void addProviderArtifactToBootClasspath( Classpath bootclasspath )
+        {
+        }
+
+        public void addProviderArtifactToSurefireClasspath( ClasspathConfiguration classpathConfiguration )
+            throws ArtifactResolutionException, ArtifactNotFoundException
+        {
+            dependencyResolver.addProviderToClasspath( classpathConfiguration, getProviderArtifactName(),
+                                                       surefireArtifact.getBaseVersion(), null );
+        }
+
+    }
 }

Added: maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireDependencyResolver.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireDependencyResolver.java?rev=1042246&view=auto
==============================================================================
--- maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireDependencyResolver.java (added)
+++ maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireDependencyResolver.java Sat Dec  4 22:16:45 2010
@@ -0,0 +1,189 @@
+package org.apache.maven.plugin.surefire;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.factory.ArtifactFactory;
+import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
+import org.apache.maven.artifact.resolver.ArtifactResolutionException;
+import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
+import org.apache.maven.artifact.resolver.ArtifactResolver;
+import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
+import org.apache.maven.artifact.resolver.filter.ExcludesArtifactFilter;
+import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
+import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
+import org.apache.maven.artifact.versioning.OverConstrainedVersionException;
+import org.apache.maven.artifact.versioning.VersionRange;
+import org.apache.maven.plugin.logging.Log;
+import org.apache.maven.surefire.booter.Classpath;
+import org.apache.maven.surefire.booter.ClasspathConfiguration;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Abstract base class for running tests using Surefire.
+ *
+ * @author Stephen Connolly
+ * @author Kristian Rosenvold
+ */
+public class SurefireDependencyResolver
+{
+
+    private final ArtifactResolver artifactResolver;
+
+    private final ArtifactFactory artifactFactory;
+
+    private final org.apache.maven.plugin.logging.Log log;
+
+    private final ArtifactRepository localRepository;
+
+    private final List remoteRepositories;
+
+    private final ArtifactMetadataSource artifactMetadataSource;
+
+    private final String pluginName;
+
+    protected SurefireDependencyResolver( ArtifactResolver artifactResolver, ArtifactFactory artifactFactory, Log log,
+                                          ArtifactRepository localRepository, List remoteRepositories,
+                                          ArtifactMetadataSource artifactMetadataSource, String pluginName )
+    {
+        this.artifactResolver = artifactResolver;
+        this.artifactFactory = artifactFactory;
+        this.log = log;
+        this.localRepository = localRepository;
+        this.remoteRepositories = remoteRepositories;
+        this.artifactMetadataSource = artifactMetadataSource;
+        this.pluginName = pluginName;
+    }
+
+
+    public boolean isWithinVersionSpec( Artifact artifact, String versionSpec )
+    {
+        if ( artifact == null )
+        {
+            return false;
+        }
+        try
+        {
+            VersionRange range = VersionRange.createFromVersionSpec( versionSpec );
+            try
+            {
+                return range.containsVersion( artifact.getSelectedVersion() );
+            }
+            catch ( NullPointerException e )
+            {
+                return range.containsVersion( new DefaultArtifactVersion( artifact.getBaseVersion() ) );
+            }
+        }
+        catch ( InvalidVersionSpecificationException e )
+        {
+            throw new RuntimeException( "Bug in plugin. Please report with stacktrace" );
+        }
+        catch ( OverConstrainedVersionException e )
+        {
+            throw new RuntimeException( "Bug in plugin. Please report with stacktrace" );
+        }
+    }
+
+    /**
+     * Return a new set containing only the artifacts accepted by the given filter.
+     *
+     * @param artifacts The unfiltered artifacts
+     * @param filter    The filter to apply
+     * @return The filtered result
+     * @noinspection UnusedDeclaration
+     */
+    public Set filterArtifacts( Set artifacts, ArtifactFilter filter )
+    {
+        Set filteredArtifacts = new LinkedHashSet();
+
+        for ( Iterator iter = artifacts.iterator(); iter.hasNext(); )
+        {
+            Artifact artifact = (Artifact) iter.next();
+            if ( !filter.include( artifact ) )
+            {
+                filteredArtifacts.add( artifact );
+            }
+        }
+
+        return filteredArtifacts;
+    }
+
+
+    public ArtifactResolutionResult resolveArtifact( Artifact filteredArtifact, Artifact providerArtifact )
+        throws ArtifactResolutionException, ArtifactNotFoundException
+    {
+        ArtifactFilter filter = null;
+        if ( filteredArtifact != null )
+        {
+            filter = new ExcludesArtifactFilter(
+                Collections.singletonList( filteredArtifact.getGroupId() + ":" + filteredArtifact.getArtifactId() ) );
+        }
+
+        Artifact originatingArtifact = artifactFactory.createBuildArtifact( "dummy", "dummy", "1.0", "jar" );
+
+        return artifactResolver.resolveTransitively( Collections.singleton( providerArtifact ), originatingArtifact,
+                                                     localRepository, remoteRepositories, artifactMetadataSource,
+                                                     filter );
+    }
+
+    public void addProviderToClasspath( ClasspathConfiguration classpathConfiguration, String provider, String version,
+                                        Artifact filteredArtifact )
+        throws ArtifactNotFoundException, ArtifactResolutionException
+    {
+        Artifact providerArtifact = artifactFactory.createDependencyArtifact( "org.apache.maven.surefire", provider,
+                                                                              VersionRange.createFromVersion( version ),
+                                                                              "jar", null, Artifact.SCOPE_TEST );
+        ArtifactResolutionResult result = resolveArtifact( filteredArtifact, providerArtifact );
+
+        for ( Iterator i = result.getArtifacts().iterator(); i.hasNext(); )
+        {
+            Artifact artifact = (Artifact) i.next();
+
+            log.debug(
+                "Adding to " + pluginName + " test classpath: " + artifact.getFile().getAbsolutePath() + " Scope: " +
+                    artifact.getScope() );
+
+            classpathConfiguration.addSurefireClasspathUrl( artifact.getFile().getAbsolutePath() );
+        }
+    }
+
+    public void addResolvedArtifactToClasspath( Classpath bootClasspath, Artifact surefireArtifact )
+        throws ArtifactNotFoundException, ArtifactResolutionException
+    {
+        ArtifactResolutionResult result = resolveArtifact( null, surefireArtifact );
+
+        for ( Iterator i = result.getArtifacts().iterator(); i.hasNext(); )
+        {
+            Artifact artifact = (Artifact) i.next();
+
+            log.debug( "Adding to " + pluginName + " booter test classpath: " + artifact.getFile().getAbsolutePath() +
+                           " Scope: " + artifact.getScope() );
+
+            bootClasspath.addClassPathElementUrl( artifact.getFile().getAbsolutePath() );
+        }
+    }
+}

Propchange: maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireDependencyResolver.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java?rev=1042246&r1=1042245&r2=1042246&view=diff
==============================================================================
--- maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java (original)
+++ maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java Sat Dec  4 22:16:45 2010
@@ -151,7 +151,7 @@ public class BooterSerializer
         properties.setProperty( BooterConstants.FAILIFNOTESTS,
                                 String.valueOf( booterConfiguration.isFailIfNoTests() ) );
         properties.setProperty( BooterConstants.PROVIDER_CONFIGURATION,
-                                surefireStarterConfiguration.getProviderFactoryClassName() );
+                                surefireStarterConfiguration.getProviderClassName() );
     }
 
     public File writePropertiesFile( String name, Properties properties )

Modified: maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkConfiguration.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkConfiguration.java?rev=1042246&r1=1042245&r2=1042246&view=diff
==============================================================================
--- maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkConfiguration.java (original)
+++ maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkConfiguration.java Sat Dec  4 22:16:45 2010
@@ -83,7 +83,7 @@ public class ForkConfiguration
         this.bootClasspathConfiguration = bootClasspathConfiguration;
     }
 
-    public Classpath getBootClasspathConfiguration()
+    public Classpath getBootClasspath()
     {
         return bootClasspathConfiguration;
     }

Modified: maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java?rev=1042246&r1=1042245&r2=1042246&view=diff
==============================================================================
--- maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java (original)
+++ maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java Sat Dec  4 22:16:45 2010
@@ -179,7 +179,7 @@ public class ForkStarter
         }
 
         final ProviderConfiguration starterConfiguration = booterConfiguration.getSurefireStarterConfiguration();
-        final Classpath bootClasspathConfiguration = forkConfiguration.getBootClasspathConfiguration();
+        final Classpath bootClasspathConfiguration = forkConfiguration.getBootClasspath();
         final Classpath additionlClassPathUrls = starterConfiguration.useSystemClassLoader()
             ? starterConfiguration.getClasspathConfiguration().getTestClasspath()
             : null;

Modified: maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerTest.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerTest.java?rev=1042246&r1=1042245&r2=1042246&view=diff
==============================================================================
--- maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerTest.java (original)
+++ maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerTest.java Sat Dec  4 22:16:45 2010
@@ -139,7 +139,7 @@ public class BooterDeserializerTest
     {
         BooterConfiguration reloaded = getReloladedConfig();
 
-        assertEquals( "com.provider", reloaded.getSurefireStarterConfiguration().getProviderFactoryClassName() );
+        assertEquals( "com.provider", reloaded.getSurefireStarterConfiguration().getProviderClassName() );
 
     }
 

Modified: maven/surefire/trunk/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java?rev=1042246&r1=1042245&r2=1042246&view=diff
==============================================================================
--- maven/surefire/trunk/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java (original)
+++ maven/surefire/trunk/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java Sat Dec  4 22:16:45 2010
@@ -31,16 +31,26 @@ import org.apache.maven.plugin.surefire.
 import org.apache.maven.project.MavenProject;
 import org.apache.maven.surefire.booter.BooterConfiguration;
 import org.apache.maven.surefire.booter.Classpath;
+import org.apache.maven.surefire.booter.ProviderDetector;
 import org.apache.maven.surefire.booter.SurefireBooterForkException;
 import org.apache.maven.surefire.booter.SurefireExecutionException;
+import org.apache.maven.surefire.providerapi.ProviderFactory;
+import org.apache.maven.surefire.providerapi.SurefireProvider;
 import org.apache.maven.toolchain.ToolchainManager;
+import org.codehaus.plexus.PlexusConstants;
+import org.codehaus.plexus.PlexusContainer;
+import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
+import org.codehaus.plexus.context.Context;
+import org.codehaus.plexus.context.ContextException;
 import org.codehaus.plexus.util.StringUtils;
 
 import java.io.File;
+import java.io.IOException;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
+import java.util.Set;
 
 /**
  * Run tests using Surefire.
@@ -55,7 +65,7 @@ import java.util.Properties;
  */
 public class SurefirePlugin
     extends AbstractSurefireMojo
-    implements SurefireExecutionParameters, SurefireReportParameters
+    implements SurefireExecutionParameters, SurefireReportParameters, org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable
 {
 
     /**
@@ -564,16 +574,36 @@ public class SurefirePlugin
      */
     private ToolchainManager toolchainManager;
 
+    private PlexusContainer container;
+
+
+    public void contextualize( Context context )
+        throws ContextException
+    {
+        container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
+    }
 
     public void execute()
         throws MojoExecutionException, MojoFailureException
     {
+        final WellKnownProvider provider = initialize();
         if ( verifyParameters() )
         {
             final Classpath bootClasspathConfiguration = new Classpath();
             ForkConfiguration forkConfiguration = getForkConfiguration(bootClasspathConfiguration);
 
-            BooterConfiguration booterConfiguration = createBooterConfiguration( forkConfiguration );
+            BooterConfiguration booterConfiguration = createBooterConfiguration( forkConfiguration, provider );
+
+            try
+            {
+                final Set objects =
+                    ProviderDetector.getServiceNames( SurefireProvider.class, Thread.currentThread().getContextClassLoader());
+                System.out.println(objects);
+            }
+            catch ( IOException e )
+            {
+                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
+            }
 
             getLog().info(
                 StringUtils.capitalizeFirstLetter( getPluginName() ) + " report directory: " + getReportsDirectory() );

Added: maven/surefire/trunk/maven-surefire-plugin/src/site/apt/examples/providers.apt.vm
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-plugin/src/site/apt/examples/providers.apt.vm?rev=1042246&view=auto
==============================================================================
--- maven/surefire/trunk/maven-surefire-plugin/src/site/apt/examples/providers.apt.vm (added)
+++ maven/surefire/trunk/maven-surefire-plugin/src/site/apt/examples/providers.apt.vm Sat Dec  4 22:16:45 2010
@@ -0,0 +1,38 @@
+ ------
+ Configuring providers
+ ------
+ Kristian Rosenvold <kr...@apache.org>
+ ------
+ 2010-12-04
+ ------
+
+Configuring providers
+
+* Selecting a provider
+
+Surefire normally automatically selects which test-framework provider to use based on the version of
+TestNG/JUnit present in your project's classpath. In some cases it may be desirable to manually
+override such a selection. This can be done by adding the required provider as a dependency to
+the surefire-plugin.
+
+The following example shows how to force the junit 4.7 provider:
++---+
+  [...]
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>${surefire.version}</version>
+                <dependencies>
+                    <dependency>
+                        <groupId>org.apache.maven.surefire</groupId>
+                        <artifactId>surefire-junit47</artifactId>
+                        <version>${surefire.version}</version>
+                    </dependency>
+                </dependencies>
+            </plugin>
+  [...]
++---+
+
+The providers supplied with surefire are surefire-junit3, surefire-junit4, surefire-junit47 and surefire-testng.
+Please note that forcing a provider still requires that the test framework is properly set up on your project classpath.
+

Propchange: maven/surefire/trunk/maven-surefire-plugin/src/site/apt/examples/providers.apt.vm
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: maven/surefire/trunk/maven-surefire-plugin/src/site/site.xml
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-plugin/src/site/site.xml?rev=1042246&r1=1042245&r2=1042246&view=diff
==============================================================================
--- maven/surefire/trunk/maven-surefire-plugin/src/site/site.xml (original)
+++ maven/surefire/trunk/maven-surefire-plugin/src/site/site.xml Sat Dec  4 22:16:45 2010
@@ -39,6 +39,7 @@
       <item name="Debugging Tests" href="examples/debugging.html"/>
       <item name="System Properties" href="examples/system-properties.html"/>
       <item name="Configuring the Classpath" href="examples/configuring-classpath.html"/>
+      <item name="Choosing providers" href="examples/providers.html"/>
     </menu>
   </body>
 </project>

Added: maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/booter/ProviderDetector.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/booter/ProviderDetector.java?rev=1042246&view=auto
==============================================================================
--- maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/booter/ProviderDetector.java (added)
+++ maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/booter/ProviderDetector.java Sat Dec  4 22:16:45 2010
@@ -0,0 +1,172 @@
+package org.apache.maven.surefire.booter;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.reflect.Array;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Stephen Conolly
+ * @author Kristian Rosenvold
+ * @noinspection UnusedDeclaration
+ */
+public class ProviderDetector
+{
+    /**
+     * Method loadServices loads the services of a class that are
+     * defined using the SPI mechanism.
+     *
+     * @param clazz       The interface / abstract class defining the service.
+     * @param classLoader of type ClassLoader the classloader to use.
+     * @return An array of instances.
+     * @throws IOException When unable to read/load the manifests
+     */
+    public static Object[] loadServices( Class clazz, ClassLoader classLoader )
+        throws IOException
+    {
+        final String resourceName = "META-INF/services/" + clazz.getName();
+
+        if ( classLoader == null )
+        {
+            return new Object[0];
+        }
+        final Enumeration urlEnumeration = classLoader.getResources( resourceName );
+        final Set names = getNames( urlEnumeration );
+        if ( names == null || names.size() == 0 )
+        {
+            return (Object[]) Array.newInstance( clazz, 0 );
+        }
+
+        return instantiateServices( clazz, classLoader, names );
+    }
+
+    public static Set getServiceNames( Class clazz, ClassLoader classLoader )
+        throws IOException
+    {
+        final String resourceName = "META-INF/services/" + clazz.getName();
+
+        if ( classLoader == null )
+        {
+            return new HashSet(  );
+        }
+        final Enumeration urlEnumeration = classLoader.getResources( resourceName );
+        return getNames( urlEnumeration );
+    }
+
+    private static Object[] instantiateServices( Class clazz, ClassLoader classLoader, Set names )
+    {
+        List result = new ArrayList();
+        for ( Iterator i = names.iterator(); i.hasNext(); )
+        {
+            String name = (String) i.next();
+            try
+            {
+                Class implClass = classLoader.loadClass( name );
+                if ( !clazz.isAssignableFrom( implClass ) )
+                {
+                    continue;
+                }
+                result.add( implClass.newInstance() );
+            }
+            catch ( ClassNotFoundException e )
+            {
+                // ignore
+            }
+            catch ( IllegalAccessException e )
+            {
+                // ignore
+            }
+            catch ( InstantiationException e )
+            {
+                // ignore
+            }
+        }
+        return result.toArray( (Object[]) Array.newInstance( clazz, result.size() ) );
+    }
+
+
+    /**
+     * Method loadServices loads the services of a class that are
+     * defined using the SPI mechanism.
+     *
+     * @param urlEnumeration The urls from the resource
+     * @throws IOException When reading the streams fails
+     * @return The set of service provider names
+     */
+    private static Set getNames( final Enumeration urlEnumeration )
+        throws IOException
+    {
+        final Set names = new HashSet();
+        nextUrl:
+        while ( urlEnumeration.hasMoreElements() )
+        {
+            final URL url = (URL) urlEnumeration.nextElement();
+            final BufferedReader reader = getReader( url );
+            try
+            {
+                String line;
+                while ( ( line = reader.readLine() ) != null )
+                {
+                    int ci = line.indexOf( '#' );
+                    if ( ci >= 0 )
+                    {
+                        line = line.substring( 0, ci );
+                    }
+                    line = line.trim();
+                    int n = line.length();
+                    if ( n == 0 )
+                    {
+                        continue; // next line
+                    }
+
+                    if ( ( line.indexOf( ' ' ) >= 0 ) || ( line.indexOf( '\t' ) >= 0 ) )
+                    {
+                        continue nextUrl; // next url
+                    }
+                    char cp = line.charAt( 0 ); // should use codePointAt but this is JDK1.3
+                    if ( !Character.isJavaIdentifierStart( cp ) )
+                    {
+                        continue nextUrl; // next url
+                    }
+                    for ( int i = 1; i < n; i++ )
+                    {
+                        cp = line.charAt( i );  // should use codePointAt but this is JDK1.3
+                        if ( !Character.isJavaIdentifierPart( cp ) && ( cp != '.' ) )
+                        {
+                            continue nextUrl; // next url
+                        }
+                    }
+                    if ( !names.contains( line ) )
+                    {
+                        names.add( line );
+                    }
+                }
+            }
+            finally
+            {
+                reader.close();
+            }
+        }
+
+        return names;
+    }
+
+
+    private static BufferedReader getReader( URL url )
+        throws IOException
+    {
+        final InputStream inputStream = url.openStream();
+        final InputStreamReader inputStreamReader = new InputStreamReader( inputStream );
+        return new BufferedReader( inputStreamReader );
+    }
+
+
+}

Propchange: maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/booter/ProviderDetector.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java?rev=1042246&r1=1042245&r2=1042246&view=diff
==============================================================================
--- maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java (original)
+++ maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java Sat Dec  4 22:16:45 2010
@@ -19,6 +19,8 @@ package org.apache.maven.surefire.booter
  * under the License.
  */
 
+import org.apache.maven.surefire.providerapi.BaseProviderFactory;
+import org.apache.maven.surefire.providerapi.BooterParameters;
 import org.apache.maven.surefire.providerapi.DirectoryScannerParametersAware;
 import org.apache.maven.surefire.providerapi.ProviderPropertiesAware;
 import org.apache.maven.surefire.providerapi.ReporterConfigurationAware;
@@ -72,6 +74,8 @@ public class SurefireReflector
 
     private final Class runResult;
 
+    private final Class booterParameters;
+
     private static final Class[] noargs = new Class[0];
 
     private static final Object[] noargsValues = new Object[0];
@@ -93,6 +97,7 @@ public class SurefireReflector
             reporterConfigurationAware = surefireClassLoader.loadClass( ReporterConfigurationAware.class.getName() );
             providerPropertiesAware = surefireClassLoader.loadClass( ProviderPropertiesAware.class.getName() );
             runResult = surefireClassLoader.loadClass( RunResult.class.getName() );
+            booterParameters= surefireClassLoader.loadClass( BooterParameters.class.getName() );
         }
         catch ( ClassNotFoundException e )
         {
@@ -221,12 +226,12 @@ public class SurefireReflector
         }
     }
 
-    public Object createProviderFactory( String providerFactoryClassName )
+    public Object createBooterConfiguration()
     {
         try
         {
 
-            Class clazz = classLoader.loadClass( providerFactoryClassName );
+            Class clazz = classLoader.loadClass( BaseProviderFactory.class.getName());
             return clazz.newInstance();
         }
         catch ( InstantiationException e )
@@ -242,11 +247,31 @@ public class SurefireReflector
             throw new RuntimeException( e );
         }
     }
-    public Object instantiateProviderByFactory( Object providerFactory )
+    public Object instantiateProvider( String providerClassName, Object booterParameters )
     {
 
-            Method createProvider = getMethod( providerFactory, "createProvider", noargs );
-        return invokeMethod( providerFactory, createProvider, noargsValues );
+        try
+        {
+            Class aClass = classLoader.loadClass( providerClassName );
+            Constructor constructor = getConstructor(  aClass,  new Class[]{ this.booterParameters } );
+            return constructor.newInstance( new Object []{booterParameters} );
+        }
+        catch ( ClassNotFoundException e )
+        {
+            throw new RuntimeException( e );
+        }
+        catch ( InvocationTargetException e )
+        {
+            throw new RuntimeException( e );
+        }
+        catch ( InstantiationException e )
+        {
+            throw new RuntimeException( e );
+        }
+        catch ( IllegalAccessException e )
+        {
+            throw new RuntimeException( e );
+        }
     }
 
 

Modified: maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/BaseProviderFactory.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/BaseProviderFactory.java?rev=1042246&r1=1042245&r2=1042246&view=diff
==============================================================================
--- maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/BaseProviderFactory.java (original)
+++ maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/BaseProviderFactory.java Sat Dec  4 22:16:45 2010
@@ -23,6 +23,7 @@ import org.apache.maven.surefire.report.
 import org.apache.maven.surefire.report.ReporterManagerFactory;
 import org.apache.maven.surefire.report.ReporterManagerFactory2;
 import org.apache.maven.surefire.testset.DirectoryScannerParameters;
+import org.apache.maven.surefire.testset.TestArtifactInfo;
 import org.apache.maven.surefire.testset.TestRequest;
 import org.apache.maven.surefire.util.DefaultDirectoryScanner;
 import org.apache.maven.surefire.util.DirectoryScanner;
@@ -32,9 +33,9 @@ import java.util.Properties;
 /**
  * @author Kristian Rosenvold
  */
-public abstract class BaseProviderFactory
+public class BaseProviderFactory
     implements DirectoryScannerParametersAware, ReporterConfigurationAware, SurefireClassLoadersAware, TestRequestAware,
-    ProviderFactory, ProviderPropertiesAware
+    ProviderPropertiesAware, BooterParameters, TestArtifactInfoAware
 {
     private Properties providerProperties;
 
@@ -48,8 +49,10 @@ public abstract class BaseProviderFactor
 
     private TestRequest testRequest;
 
+    private TestArtifactInfo testArtifactInfo;
 
-    protected DirectoryScanner getDirectoryScanner()
+
+    public DirectoryScanner getDirectoryScanner()
     {
         if ( directoryScannerParameters == null )
         {
@@ -60,7 +63,7 @@ public abstract class BaseProviderFactor
                                             directoryScannerParameters.getExcludes() );
     }
 
-    protected ReporterManagerFactory getReporterManagerFactory()
+    public ReporterManagerFactory getReporterManagerFactory()
     {
         ReporterManagerFactory reporterManagerFactory =
             new ReporterManagerFactory2( surefireClassLoader, reporterConfiguration );
@@ -92,22 +95,22 @@ public abstract class BaseProviderFactor
         this.testRequest = testRequest;
     }
 
-    protected DirectoryScannerParameters getDirectoryScannerParameters()
+    public DirectoryScannerParameters getDirectoryScannerParameters()
     {
         return directoryScannerParameters;
     }
 
-    protected ReporterConfiguration getReporterConfiguration()
+    public ReporterConfiguration getReporterConfiguration()
     {
         return reporterConfiguration;
     }
 
-    protected TestRequest getTestRequest()
+    public TestRequest getTestRequest()
     {
         return testRequest;
     }
 
-    protected ClassLoader getTestClassLoader()
+    public ClassLoader getTestClassLoader()
     {
         return testClassLoader;
     }
@@ -116,4 +119,19 @@ public abstract class BaseProviderFactor
     {
         this.providerProperties = providerProperties;
     }
+
+    public Properties getProviderProperties()
+    {
+        return providerProperties;
+    }
+
+    public TestArtifactInfo getTestArtifactInfo()
+    {
+        return testArtifactInfo;
+    }
+
+    public void setTestArtifactInfo( TestArtifactInfo testArtifactInfo )
+    {
+        this.testArtifactInfo = testArtifactInfo;
+    }
 }

Added: maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/BooterParameters.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/BooterParameters.java?rev=1042246&view=auto
==============================================================================
--- maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/BooterParameters.java (added)
+++ maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/BooterParameters.java Sat Dec  4 22:16:45 2010
@@ -0,0 +1,34 @@
+package org.apache.maven.surefire.providerapi;
+
+import org.apache.maven.surefire.report.ReporterConfiguration;
+import org.apache.maven.surefire.report.ReporterManagerFactory;
+import org.apache.maven.surefire.testset.DirectoryScannerParameters;
+import org.apache.maven.surefire.testset.TestArtifactInfo;
+import org.apache.maven.surefire.testset.TestRequest;
+import org.apache.maven.surefire.util.DirectoryScanner;
+
+import java.util.Properties;
+
+/**
+ * Injected into the providers upon provider construction. Allows the provider to request services and data it needs.
+ *
+ * @author Kristian Rosenvold
+ */
+public interface BooterParameters
+{
+    DirectoryScanner getDirectoryScanner();
+
+    ReporterManagerFactory getReporterManagerFactory();
+
+    DirectoryScannerParameters getDirectoryScannerParameters();
+
+    ReporterConfiguration getReporterConfiguration();
+
+    TestRequest getTestRequest();
+
+    ClassLoader getTestClassLoader();
+
+    Properties getProviderProperties();
+
+    TestArtifactInfo getTestArtifactInfo();
+}

Propchange: maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/BooterParameters.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/SurefireProvider.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/SurefireProvider.java?rev=1042246&r1=1042245&r2=1042246&view=diff
==============================================================================
--- maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/SurefireProvider.java (original)
+++ maven/surefire/trunk/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/SurefireProvider.java Sat Dec  4 22:16:45 2010
@@ -33,6 +33,11 @@ import java.util.Iterator;
 public interface SurefireProvider
 {
     /**
+     * Returns true if the general dependencies/configuration of the environment allows this provider to run.
+     * @return
+     */
+    Boolean isRunnable();
+    /**
      * Called when forkmode is pertest, allows the provider to define what "pertest" will be.
      *
      * @return

Modified: maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderConfiguration.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderConfiguration.java?rev=1042246&r1=1042245&r2=1042246&view=diff
==============================================================================
--- maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderConfiguration.java (original)
+++ maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderConfiguration.java Sat Dec  4 22:16:45 2010
@@ -26,7 +26,7 @@ package org.apache.maven.surefire.booter
  */
 public class ProviderConfiguration
 {
-    private final String providerFactoryClassName;
+    private final String providerClassName;
 
     private final ClasspathConfiguration classpathConfiguration;
 
@@ -39,11 +39,11 @@ public class ProviderConfiguration
     private final boolean redirectTestOutputToFile;
 
 
-    public ProviderConfiguration( String providerFactoryClassName, ClasspathConfiguration classpathConfiguration,
+    public ProviderConfiguration( String providerClassName, ClasspathConfiguration classpathConfiguration,
                                   ClassLoaderConfiguration classLoaderConfiguration, boolean forkRequested,
                                   boolean inForkedVm, boolean redirectTestOutputToFile )
     {
-        this.providerFactoryClassName = providerFactoryClassName;
+        this.providerClassName = providerClassName;
         this.classpathConfiguration = classpathConfiguration;
         this.classLoaderConfiguration = classLoaderConfiguration;
         isForkRequested = forkRequested;
@@ -77,9 +77,9 @@ public class ProviderConfiguration
         return redirectTestOutputToFile;
     }
 
-    public String getProviderFactoryClassName()
+    public String getProviderClassName()
     {
-        return providerFactoryClassName;
+        return providerClassName;
     }
 
 }

Modified: maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderFactory.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderFactory.java?rev=1042246&r1=1042245&r2=1042246&view=diff
==============================================================================
--- maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderFactory.java (original)
+++ maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderFactory.java Sat Dec  4 22:16:45 2010
@@ -54,7 +54,7 @@ public class ProviderFactory
 
         ProviderConfiguration starterConfiguration = booterConfiguration.getSurefireStarterConfiguration();
         final Object o =
-            surefireReflector.createProviderFactory( starterConfiguration.getProviderFactoryClassName() );
+            surefireReflector.createBooterConfiguration();
         surefireReflector.setTestSuiteDefinitionAware( o, booterConfiguration.getTestSuiteDefinition() );
         surefireReflector.setProviderPropertiesAware( o, booterConfiguration.getProviderProperties() );
         surefireReflector.setReporterConfigurationAware( o, booterConfiguration.getReporterConfiguration() );
@@ -62,7 +62,7 @@ public class ProviderFactory
         surefireReflector.setTestArtifactInfoAware( o, booterConfiguration.getTestNg() );
         surefireReflector.setIfDirScannerAware( o, booterConfiguration.getDirScannerParams() );
 
-        Object provider = surefireReflector.instantiateProviderByFactory( o );
+        Object provider = surefireReflector.instantiateProvider( starterConfiguration.getProviderClassName(), o );
         Thread.currentThread().setContextClassLoader( context );
 
         return createClassLoaderProxy( provider );

Modified: maven/surefire/trunk/surefire-integration-tests/pom.xml
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-integration-tests/pom.xml?rev=1042246&r1=1042245&r2=1042246&view=diff
==============================================================================
--- maven/surefire/trunk/surefire-integration-tests/pom.xml (original)
+++ maven/surefire/trunk/surefire-integration-tests/pom.xml Sat Dec  4 22:16:45 2010
@@ -62,7 +62,7 @@
     </dependency>
     <dependency>
       <groupId>org.apache.maven.surefire</groupId>
-      <artifactId>surefire-junit</artifactId>
+      <artifactId>surefire-junit3</artifactId>
       <version>${project.version}</version>
     </dependency>
     <dependency>

Added: maven/surefire/trunk/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/Surefire408ManualProviderSelectionIT.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/Surefire408ManualProviderSelectionIT.java?rev=1042246&view=auto
==============================================================================
--- maven/surefire/trunk/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/Surefire408ManualProviderSelectionIT.java (added)
+++ maven/surefire/trunk/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/Surefire408ManualProviderSelectionIT.java Sat Dec  4 22:16:45 2010
@@ -0,0 +1,50 @@
+package org.apache.maven.surefire.its;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+import org.apache.maven.it.Verifier;
+import org.apache.maven.it.util.ResourceExtractor;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+/**
+ * SUREFIRE-613 Asserts proper test counts when running in parallel
+ *
+ * @author Kristian Rosenvold
+ */
+public class Surefire408ManualProviderSelectionIT
+    extends AbstractSurefireIntegrationTestClass
+{
+    public void testPaallelBuildResultCount()
+        throws Exception
+    {
+        File testDir = ResourceExtractor.simpleExtractResources( getClass(), "/surefire-408-manual-provider-selection" );
+
+        Verifier verifier = new Verifier( testDir.getAbsolutePath() );
+        String[] opts = { "-X" };
+        verifier.setCliOptions( new ArrayList( Arrays.asList( opts ) ) );
+        this.executeGoal( verifier, "test" );
+        verifier.resetStreams();
+
+        verifier.verifyTextInLog("Using explicitly configured provider org.apache.maven.surefire.junit.JUnit3Provider");
+    }
+}
\ No newline at end of file

Propchange: maven/surefire/trunk/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/Surefire408ManualProviderSelectionIT.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: maven/surefire/trunk/surefire-integration-tests/src/test/resources/surefire-408-manual-provider-selection/pom.xml
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-integration-tests/src/test/resources/surefire-408-manual-provider-selection/pom.xml?rev=1042246&view=auto
==============================================================================
--- maven/surefire/trunk/surefire-integration-tests/src/test/resources/surefire-408-manual-provider-selection/pom.xml (added)
+++ maven/surefire/trunk/surefire-integration-tests/src/test/resources/surefire-408-manual-provider-selection/pom.xml Sat Dec  4 22:16:45 2010
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+  -->
+
+<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/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>org.apache.maven.plugins.surefire</groupId>
+    <artifactId>junit-twoTestCases</artifactId>
+    <version>1.0-SNAPSHOT</version>
+    <name>Test for two test cases</name>
+
+    <dependencies>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.8.1</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>${surefire.version}</version>
+                <dependencies>
+                    <dependency>
+                        <groupId>org.apache.maven.surefire</groupId>
+                        <artifactId>surefire-junit3</artifactId>
+                        <version>${surefire.version}</version>
+                    </dependency>
+                    <!-- dependency>
+                        <groupId>org.apache.maven.surefire</groupId>
+                        <artifactId>surefire-junit4</artifactId>
+                        <version>${surefire.version}</version>
+                    </dependency>
+                    <dependency>
+                        <groupId>org.apache.maven.surefire</groupId>
+                        <artifactId>surefire-junit3</artifactId>
+                        <version>${surefire.version}</version>
+                    </dependency>
+                    <dependency>
+                        <groupId>org.apache.maven.surefire</groupId>
+                        <artifactId>surefire-testng</artifactId>
+                        <version>${surefire.version}</version>
+                    </dependency -->
+                </dependencies>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

Propchange: maven/surefire/trunk/surefire-integration-tests/src/test/resources/surefire-408-manual-provider-selection/pom.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: maven/surefire/trunk/surefire-integration-tests/src/test/resources/surefire-408-manual-provider-selection/src/test/java/junit/twoTestCases/BasicTest.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-integration-tests/src/test/resources/surefire-408-manual-provider-selection/src/test/java/junit/twoTestCases/BasicTest.java?rev=1042246&view=auto
==============================================================================
--- maven/surefire/trunk/surefire-integration-tests/src/test/resources/surefire-408-manual-provider-selection/src/test/java/junit/twoTestCases/BasicTest.java (added)
+++ maven/surefire/trunk/surefire-integration-tests/src/test/resources/surefire-408-manual-provider-selection/src/test/java/junit/twoTestCases/BasicTest.java Sat Dec  4 22:16:45 2010
@@ -0,0 +1,67 @@
+package junit.twoTestCases;
+import junit.extensions.TestSetup;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+public class BasicTest
+    extends TestCase
+{
+
+    private boolean setUpCalled = false;
+
+    private static boolean tearDownCalled = false;
+
+    public BasicTest( String name, String extraName )
+    {
+        super( name );
+    }
+
+    public static Test suite()
+    {
+        TestSuite suite = new TestSuite();
+        Test test = new BasicTest( "testSetUp", "dummy" );
+        suite.addTest( test );
+        TestSetup setup = new TestSetup( suite )
+        {
+
+            protected void setUp()
+            {
+                //oneTimeSetUp();
+            }
+
+            protected void tearDown()
+            {
+                oneTimeTearDown();
+            }
+
+        };
+
+        return setup;
+    }
+
+    protected void setUp()
+    {
+        setUpCalled = true;
+        tearDownCalled = false;
+        System.out.println( "Called setUp" );
+    }
+
+    protected void tearDown()
+    {
+        setUpCalled = false;
+        tearDownCalled = true;
+        System.out.println( "Called tearDown" );
+    }
+
+    public void testSetUp()
+    {
+        assertTrue( "setUp was not called", setUpCalled );
+    }
+
+    public static void oneTimeTearDown()
+    {
+        assertTrue( "tearDown was not called", tearDownCalled );
+    }
+
+}

Propchange: maven/surefire/trunk/surefire-integration-tests/src/test/resources/surefire-408-manual-provider-selection/src/test/java/junit/twoTestCases/BasicTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: maven/surefire/trunk/surefire-integration-tests/src/test/resources/surefire-408-manual-provider-selection/src/test/java/junit/twoTestCases/TestTwo.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-integration-tests/src/test/resources/surefire-408-manual-provider-selection/src/test/java/junit/twoTestCases/TestTwo.java?rev=1042246&view=auto
==============================================================================
--- maven/surefire/trunk/surefire-integration-tests/src/test/resources/surefire-408-manual-provider-selection/src/test/java/junit/twoTestCases/TestTwo.java (added)
+++ maven/surefire/trunk/surefire-integration-tests/src/test/resources/surefire-408-manual-provider-selection/src/test/java/junit/twoTestCases/TestTwo.java Sat Dec  4 22:16:45 2010
@@ -0,0 +1,9 @@
+package junit.twoTestCases;
+import junit.framework.TestCase;
+
+
+public class TestTwo
+    extends TestCase
+{
+    public void testTwo() {}
+}

Propchange: maven/surefire/trunk/surefire-integration-tests/src/test/resources/surefire-408-manual-provider-selection/src/test/java/junit/twoTestCases/TestTwo.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: maven/surefire/trunk/surefire-providers/surefire-junit/pom.xml
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-providers/surefire-junit/pom.xml?rev=1042246&r1=1042245&r2=1042246&view=diff
==============================================================================
--- maven/surefire/trunk/surefire-providers/surefire-junit/pom.xml (original)
+++ maven/surefire/trunk/surefire-providers/surefire-junit/pom.xml Sat Dec  4 22:16:45 2010
@@ -27,10 +27,19 @@
     <relativePath>../pom.xml</relativePath>
   </parent>
 
-  <artifactId>surefire-junit</artifactId>
+  <artifactId>surefire-junit3</artifactId>
 
   <name>SureFire JUnit Runner</name>
 
+    <build>
+    <resources>
+      <resource>
+        <directory>src/main/resources/META-INF</directory>
+        <targetPath>META-INF</targetPath>
+      </resource>
+    </resources>
+
+    </build>
   <dependencies>
     <dependency>
       <groupId>junit</groupId>

Modified: maven/surefire/trunk/surefire-providers/surefire-junit/src/main/java/org/apache/maven/surefire/junit/JUnit3Provider.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-providers/surefire-junit/src/main/java/org/apache/maven/surefire/junit/JUnit3Provider.java?rev=1042246&r1=1042245&r2=1042246&view=diff
==============================================================================
--- maven/surefire/trunk/surefire-providers/surefire-junit/src/main/java/org/apache/maven/surefire/junit/JUnit3Provider.java (original)
+++ maven/surefire/trunk/surefire-providers/surefire-junit/src/main/java/org/apache/maven/surefire/junit/JUnit3Provider.java Sat Dec  4 22:16:45 2010
@@ -19,6 +19,7 @@ package org.apache.maven.surefire.junit;
  * under the License.
  */
 
+import org.apache.maven.surefire.providerapi.BooterParameters;
 import org.apache.maven.surefire.providerapi.SurefireProvider;
 import org.apache.maven.surefire.report.ReporterException;
 import org.apache.maven.surefire.report.ReporterManagerFactory;
@@ -41,12 +42,11 @@ public class JUnit3Provider
 
     private final DirectoryScanner directoryScanner;
 
-    public JUnit3Provider( ReporterManagerFactory reporterManagerFactory, ClassLoader testClassLoader,
-                           DirectoryScanner directoryScanner )
+    public JUnit3Provider( BooterParameters booterParameters )
     {
-        this.reporterManagerFactory = reporterManagerFactory;
-        this.testClassLoader = testClassLoader;
-        this.directoryScanner = directoryScanner;
+        this.reporterManagerFactory = booterParameters.getReporterManagerFactory();
+        this.testClassLoader = booterParameters.getTestClassLoader();
+        this.directoryScanner = booterParameters.getDirectoryScanner();
     }
 
     public RunResult invoke( Object forkTestSet )
@@ -85,4 +85,9 @@ public class JUnit3Provider
             throw new RuntimeException( e );
         }
     }
+
+    public Boolean isRunnable()
+    {
+        return Boolean.TRUE;
+    }
 }

Added: maven/surefire/trunk/surefire-providers/surefire-junit/src/main/resources/META-INF/services/org.apache.maven.surefire.providerapi.SurefireProvider
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-providers/surefire-junit/src/main/resources/META-INF/services/org.apache.maven.surefire.providerapi.SurefireProvider?rev=1042246&view=auto
==============================================================================
--- maven/surefire/trunk/surefire-providers/surefire-junit/src/main/resources/META-INF/services/org.apache.maven.surefire.providerapi.SurefireProvider (added)
+++ maven/surefire/trunk/surefire-providers/surefire-junit/src/main/resources/META-INF/services/org.apache.maven.surefire.providerapi.SurefireProvider Sat Dec  4 22:16:45 2010
@@ -0,0 +1 @@
+org.apache.maven.surefire.junit.JUnit3Provider

Modified: maven/surefire/trunk/surefire-providers/surefire-junit4/pom.xml
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-providers/surefire-junit4/pom.xml?rev=1042246&r1=1042245&r2=1042246&view=diff
==============================================================================
--- maven/surefire/trunk/surefire-providers/surefire-junit4/pom.xml (original)
+++ maven/surefire/trunk/surefire-providers/surefire-junit4/pom.xml Sat Dec  4 22:16:45 2010
@@ -41,6 +41,13 @@
   </dependencies>
 
   <build>
+    <resources>
+      <resource>
+        <directory>src/main/resources/META-INF</directory>
+        <targetPath>META-INF</targetPath>
+      </resource>
+    </resources>
+
     <plugins>
       <plugin>
         <artifactId>maven-compiler-plugin</artifactId>

Modified: maven/surefire/trunk/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java?rev=1042246&r1=1042245&r2=1042246&view=diff
==============================================================================
--- maven/surefire/trunk/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java (original)
+++ maven/surefire/trunk/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java Sat Dec  4 22:16:45 2010
@@ -19,6 +19,7 @@ package org.apache.maven.surefire.junit4
  * under the License.
  */
 
+import org.apache.maven.surefire.providerapi.BooterParameters;
 import org.apache.maven.surefire.providerapi.SurefireProvider;
 import org.apache.maven.surefire.report.ReporterException;
 import org.apache.maven.surefire.report.ReporterManagerFactory;
@@ -42,12 +43,11 @@ public class JUnit4Provider
 
     private final DirectoryScanner directoryScanner;
 
-    public JUnit4Provider( ReporterManagerFactory reporterManagerFactory, ClassLoader testClassLoader,
-                           DirectoryScanner directoryScanner )
+    public JUnit4Provider( BooterParameters booterParameters )
     {
-        this.reporterManagerFactory = reporterManagerFactory;
-        this.testClassLoader = testClassLoader;
-        this.directoryScanner = directoryScanner;
+        this.reporterManagerFactory = booterParameters.getReporterManagerFactory();
+        this.testClassLoader = booterParameters.getTestClassLoader();
+        this.directoryScanner = booterParameters.getDirectoryScanner();
     }
 
     @SuppressWarnings( { "UnnecessaryUnboxing" } )
@@ -112,4 +112,10 @@ public class JUnit4Provider
         return property != null;
     }
 
+    public Boolean isRunnable()
+    {
+        return Boolean.TRUE;
+    }
+
+
 }

Added: maven/surefire/trunk/surefire-providers/surefire-junit4/src/main/resources/META-INF/services/org.apache.maven.surefire.providerapi.SurefireProvider
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-providers/surefire-junit4/src/main/resources/META-INF/services/org.apache.maven.surefire.providerapi.SurefireProvider?rev=1042246&view=auto
==============================================================================
--- maven/surefire/trunk/surefire-providers/surefire-junit4/src/main/resources/META-INF/services/org.apache.maven.surefire.providerapi.SurefireProvider (added)
+++ maven/surefire/trunk/surefire-providers/surefire-junit4/src/main/resources/META-INF/services/org.apache.maven.surefire.providerapi.SurefireProvider Sat Dec  4 22:16:45 2010
@@ -0,0 +1 @@
+org.apache.maven.surefire.junit4.JUnit4Provider

Modified: maven/surefire/trunk/surefire-providers/surefire-junit47/pom.xml
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-providers/surefire-junit47/pom.xml?rev=1042246&r1=1042245&r2=1042246&view=diff
==============================================================================
--- maven/surefire/trunk/surefire-providers/surefire-junit47/pom.xml (original)
+++ maven/surefire/trunk/surefire-providers/surefire-junit47/pom.xml Sat Dec  4 22:16:45 2010
@@ -51,6 +51,13 @@
     </dependencies>
 
     <build>
+           <resources>
+             <resource>
+               <directory>src/main/resources/META-INF</directory>
+               <targetPath>META-INF</targetPath>
+             </resource>
+           </resources>
+
         <plugins>
             <plugin>
                 <artifactId>maven-compiler-plugin</artifactId>