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 2011/02/16 23:17:40 UTC

svn commit: r1071421 - in /maven/surefire/trunk: maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ surefire-booter/src/main/java/org/apache/maven/sur...

Author: krosenvold
Date: Wed Feb 16 22:17:38 2011
New Revision: 1071421

URL: http://svn.apache.org/viewvc?rev=1071421&view=rev
Log:
[SUREFIRE-700] Isolate surefire from itself

o Introduces a third classloader that is parent of
testClassLoader and providerClassLoader.

In this case, providerClassLoader is totatlly
unrelated to the testClassLoader, which
increases isolation.

API and booter module are still shared
Only active when forking with manifest-only-jar

Modified:
    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/ProviderInfo.java
    maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireDependencyResolver.java
    maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java
    maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterConstants.java
    maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterDeserializer.java
    maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/Classpath.java
    maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ClasspathConfiguration.java
    maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java
    maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/IsolatedClassLoader.java
    maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreRunListener.java
    maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/TestSet.java

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=1071421&r1=1071420&r2=1071421&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 Wed Feb 16 22:17:38 2011
@@ -99,47 +99,45 @@ public abstract class AbstractSurefireMo
         if ( verifyParameters() && !hasExecutedBefore() )
         {
             logReportsDirectory();
-        	executeAfterPreconditionsChecked();
+            executeAfterPreconditionsChecked();
         }
     }
 
     protected boolean verifyParameters()
         throws MojoFailureException
-	{
-	    if ( isSkipExecution() )
-	    {
-	        getLog().info( "Tests are skipped." );
-	        return false;
-	    }
-	
-	    if ( !getTestClassesDirectory().exists() )
-	    {
-	        if ( Boolean.TRUE.equals(getFailIfNoTests()) )
-	        {
-	            throw new MojoFailureException( "No tests to run!" );
-	        }
-	        getLog().info( "No tests to run." );
-	    }
-	    else
-	    {
-	        ensureWorkingDirectoryExists();
-	        ensureParallelRunningCompatibility();
-	        warnIfUselessUseSystemClassLoaderParameter();
-	    }
-	
-	    return true;
-	}
-    
+    {
+        if ( isSkipExecution() )
+        {
+            getLog().info( "Tests are skipped." );
+            return false;
+        }
+
+        if ( !getTestClassesDirectory().exists() )
+        {
+            if ( Boolean.TRUE.equals( getFailIfNoTests() ) )
+            {
+                throw new MojoFailureException( "No tests to run!" );
+            }
+            getLog().info( "No tests to run." );
+        }
+        else
+        {
+            ensureWorkingDirectoryExists();
+            ensureParallelRunningCompatibility();
+            warnIfUselessUseSystemClassLoaderParameter();
+        }
+
+        return true;
+    }
+
     protected abstract boolean isSkipExecution();
-    
+
     protected abstract void executeAfterPreconditionsChecked()
         throws MojoExecutionException, MojoFailureException;
 
     private Artifact surefireArtifact;
 
 
-    private ProviderList wellKnownProviders;
-
     protected List initialize()
         throws MojoFailureException
     {
@@ -150,10 +148,12 @@ public abstract class AbstractSurefireMo
         try
         {
             final Artifact junitDepArtifact = getJunitDepArtifact();
-            wellKnownProviders = new ProviderList( new ProviderInfo[]{ new TestNgProviderInfo( getTestNgArtifact() ),
-                new JUnitCoreProviderInfo( getJunitArtifact(), junitDepArtifact ),
-                new JUnit4ProviderInfo( getJunitArtifact(), junitDepArtifact ), new JUnit3ProviderInfo() },
-                                                   new DynamicProviderInfo( null ) );
+
+            ProviderList wellKnownProviders = new ProviderList(
+                new ProviderInfo[]{ new TestNgProviderInfo( getTestNgArtifact() ),
+                    new JUnitCoreProviderInfo( getJunitArtifact(), junitDepArtifact ),
+                    new JUnit4ProviderInfo( getJunitArtifact(), junitDepArtifact ),
+                    new JUnit3ProviderInfo( getJunitArtifact() ) }, new DynamicProviderInfo( null ) );
 
             return wellKnownProviders.resolve( getLog() );
         }
@@ -276,34 +276,16 @@ public abstract class AbstractSurefireMo
             new ReporterConfiguration( reports, getReportsDirectory(), Boolean.valueOf( isTrimStackTrace() ),
                                        timeoutSet );
 
-        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" );
-        }
-
-        surefireArtifact.isSnapshot(); // MNG-2961: before Maven 2.0.8, fixes getBaseVersion to be -SNAPSHOT if needed
-
         Artifact testNgArtifact;
         try
         {
-            addArtifact( forkConfiguration.getBootClasspath(), surefireArtifact );
 
             testNgArtifact = getTestNgArtifact();
         }
-        catch ( ArtifactNotFoundException e )
-        {
-            throw new MojoExecutionException(
-                "Unable to locate required surefire provider dependency: " + e.getMessage(), e );
-        }
         catch ( InvalidVersionSpecificationException e )
         {
             throw new MojoExecutionException( "Error determining the TestNG version requested: " + e.getMessage(), e );
         }
-        catch ( ArtifactResolutionException e )
-        {
-            throw new MojoExecutionException( "Error to resolving surefire provider dependency: " + e.getMessage(), e );
-        }
 
         DirectoryScannerParameters directoryScannerParameters = null;
         final boolean isTestNg = testNgArtifact != null;
@@ -374,25 +356,21 @@ public abstract class AbstractSurefireMo
                                                                ClassLoaderConfiguration classLoaderConfiguration )
         throws MojoExecutionException, MojoFailureException
     {
-        final ClasspathConfiguration classpathConfiguration =
-            new ClasspathConfiguration( isEnableAssertions(), isChildDelegation() );
-
-        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" );
-        }
-
-        surefireArtifact.isSnapshot(); // MNG-2961: before Maven 2.0.8, fixes getBaseVersion to be -SNAPSHOT if needed
-
-        String providerName;
         try
         {
-            addArtifact( forkConfiguration.getBootClasspath(), surefireArtifact );
-
             provider.addProviderProperties();
-            provider.addProviderArtifactToSurefireClasspath( classpathConfiguration );
-            providerName = provider.getProviderName();
+
+            String providerName = provider.getProviderName();
+            Classpath providerClasspath = provider.getProviderClasspath();
+            Classpath testClasspath = generateTestClasspath();
+
+            final ClasspathConfiguration classpathConfiguration =
+                new ClasspathConfiguration( testClasspath, providerClasspath, provider.getTestframeworkClasspath(),
+                                            isEnableAssertions(), isChildDelegation() );
+
+            logClasspath( testClasspath, "Test" );
+            return new StartupConfiguration( providerName, classpathConfiguration, classLoaderConfiguration,
+                                             forkConfiguration.isForking(), false, isRedirectTestOutputToFile() );
         }
         catch ( ArtifactNotFoundException e )
         {
@@ -403,40 +381,30 @@ public abstract class AbstractSurefireMo
         {
             throw new MojoExecutionException( "Error to resolving surefire provider dependency: " + e.getMessage(), e );
         }
-
-        List classpathElements;
-        try
-        {
-            classpathElements = generateTestClasspath();
-        }
         catch ( DependencyResolutionRequiredException e )
         {
             throw new MojoExecutionException( "Unable to generate test classpath: " + e, e );
         }
-
-        addClasspathElementsToClasspathConfiguration(classpathElements, classpathConfiguration);
-        return new StartupConfiguration( providerName, classpathConfiguration, classLoaderConfiguration,
-                                         forkConfiguration.isForking(), false, isRedirectTestOutputToFile() );
     }
 
-    private void addClasspathElementsToClasspathConfiguration(List classpathElements, ClasspathConfiguration classpathConfiguration)
+    public void logClasspath( Classpath classpath, String descriptor )
     {
-        getLog().debug( "Test classpath:" );
-        for ( Iterator i = classpathElements.iterator(); i.hasNext(); )
+        getLog().debug( descriptor + " classpath:" );
+        for ( Iterator i = classpath.getClassPath().iterator(); i.hasNext(); )
         {
             String classpathElement = (String) i.next();
             if ( classpathElement == null )
             {
-                getLog().warn("The test classpath contains a null element.");
+                getLog().warn( "The test classpath contains a null element." );
             }
             else
             {
                 getLog().debug( "  " + classpathElement );
-                classpathConfiguration.addClasspathUrl( classpathElement );
             }
         }
     }
 
+
     private boolean isSpecificTestSpecified()
     {
         return getTest() != null;
@@ -525,8 +493,8 @@ public abstract class AbstractSurefireMo
             if ( !range.containsVersion( new DefaultArtifactVersion( artifact.getVersion() ) ) )
             {
                 throw new MojoFailureException(
-                    "TestNG support requires version 4.7 or above. You have declared version " +
-                        artifact.getVersion() );
+                    "TestNG support requires version 4.7 or above. You have declared version "
+                        + artifact.getVersion() );
             }
         }
         return artifact;
@@ -555,12 +523,35 @@ public abstract class AbstractSurefireMo
     }
 
     protected ForkConfiguration getForkConfiguration()
+        throws MojoExecutionException
     {
         File tmpDir = getSurefireTempDir();
         //noinspection ResultOfMethodCallIgnored
         tmpDir.mkdirs();
 
-        final Classpath bootClasspathConfiguration = new Classpath();
+        final Classpath bootClasspathConfiguration;
+        try
+        {
+            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" );
+            }
+
+            surefireArtifact.isSnapshot(); // MNG-2961: before Maven 2.0.8, fixes getBaseVersion to be -SNAPSHOT if needed
+
+            bootClasspathConfiguration = dependencyResolver.getResolvedArtifactClasspath( surefireArtifact );
+
+        }
+        catch ( ArtifactNotFoundException e )
+        {
+            throw new MojoExecutionException(
+                "Unable to locate required surefire provider dependency: " + e.getMessage(), e );
+        }
+        catch ( ArtifactResolutionException e )
+        {
+            throw new MojoExecutionException( "Error to resolving surefire provider dependency: " + e.getMessage(), e );
+        }
 
         ForkConfiguration fork = new ForkConfiguration( bootClasspathConfiguration, getForkMode(), tmpDir );
 
@@ -628,12 +619,12 @@ public abstract class AbstractSurefireMo
         return fork;
     }
 
-
     /**
      * Where surefire stores its own temp files
      *
      * @return A file pointing to the location of surefire's own temp files
      */
+
     private File getSurefireTempDir()
     {
         return new File( getReportsDirectory().getParentFile(), "surefire" );
@@ -730,7 +721,7 @@ public abstract class AbstractSurefireMo
      * @throws org.apache.maven.plugin.MojoExecutionException
      *          upon other problems
      */
-    public List generateTestClasspath()
+    public Classpath generateTestClasspath()
         throws DependencyResolutionRequiredException, MojoExecutionException
     {
         List classpath = new ArrayList( 2 + getProject().getArtifacts().size() );
@@ -772,11 +763,14 @@ public abstract class AbstractSurefireMo
             for ( Iterator iter = getAdditionalClasspathElements().iterator(); iter.hasNext(); )
             {
                 String classpathElement = (String) iter.next();
-                classpath.add( classpathElement );
+                if ( classpathElement != null )
+                {
+                    classpath.add( classpathElement );
+                }
             }
         }
 
-        return classpath;
+        return new Classpath( classpath );
     }
 
     /**
@@ -830,23 +824,6 @@ public abstract class AbstractSurefireMo
                                                           getRemoteRepositories(), getMetadataSource(), filter );
     }
 
-    private void addArtifact( 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();
-
-            getLog().debug(
-                "Adding to " + getPluginName() + " booter test classpath: " + artifact.getFile().getAbsolutePath() +
-                    " Scope: " + artifact.getScope() );
-
-            bootClasspath.addClassPathElementUrl( artifact.getFile().getAbsolutePath() );
-        }
-    }
-
     protected void processSystemProperties( boolean setInSystem )
     {
         copyPropertiesToInternalSystemProperties( getSystemProperties() );
@@ -918,8 +895,8 @@ public abstract class AbstractSurefireMo
         }
         catch ( Exception e )
         {
-            String msg = "Build uses Maven 2.0.x, cannot propagate system properties" +
-                " from command line to tests (cf. SUREFIRE-121)";
+            String msg = "Build uses Maven 2.0.x, cannot propagate system properties"
+                + " from command line to tests (cf. SUREFIRE-121)";
             if ( getLog().isDebugEnabled() )
             {
                 getLog().warn( msg, e );
@@ -1060,24 +1037,67 @@ public abstract class AbstractSurefireMo
             return testNgArtifact != null;
         }
 
+        public Classpath getTestframeworkClasspath()
+        {
+            return new Classpath( testNgArtifact.getFile() );
+        }
+
         public void addProviderProperties()
         {
             convertTestNGParameters();
         }
 
-        public void addProviderArtifactToSurefireClasspath( ClasspathConfiguration bootclasspath )
+        public Classpath getProviderClasspath()
             throws ArtifactResolutionException, ArtifactNotFoundException
         {
             Artifact surefireArtifact =
                 (Artifact) getPluginArtifactMap().get( "org.apache.maven.surefire:surefire-booter" );
-            dependencyResolver.addProviderToClasspath( bootclasspath, "surefire-testng",
-                                                       surefireArtifact.getBaseVersion(), testNgArtifact );
+            return dependencyResolver.getProviderClasspath( "surefire-testng", surefireArtifact.getBaseVersion(),
+                                                            testNgArtifact );
         }
     }
 
-    class JUnit3ProviderInfo
+    private static abstract class JUnitProvider
         implements ProviderInfo
     {
+        protected final Artifact junitArtifact;
+
+        JUnitProvider( Artifact junitArtifact )
+        {
+            this.junitArtifact = junitArtifact;
+        }
+    }
+
+    private static abstract class JUnit4Provider
+        extends JUnitProvider
+    {
+        protected final Artifact junitDepArtifact;
+
+        JUnit4Provider( Artifact junitArtifact, Artifact junitDepArtifact )
+        {
+            super( junitArtifact );
+            this.junitDepArtifact = junitDepArtifact;
+        }
+
+        protected Artifact getArtifactToUse()
+        {
+            return junitDepArtifact != null ? junitDepArtifact : junitArtifact;
+        }
+
+        public Classpath getTestframeworkClasspath()
+        {
+            return new Classpath( getArtifactToUse().getFile() );
+        }
+    }
+
+    class JUnit3ProviderInfo
+        extends JUnitProvider
+    {
+        JUnit3ProviderInfo( Artifact junitArtifact )
+        {
+            super( junitArtifact );
+        }
+
         public String getProviderName()
         {
             return "org.apache.maven.surefire.junit.JUnit3Provider";
@@ -1092,29 +1112,31 @@ public abstract class AbstractSurefireMo
         {
         }
 
-        public void addProviderArtifactToSurefireClasspath( ClasspathConfiguration classpathConfiguration )
+        public Classpath getProviderClasspath()
             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, "surefire-junit3",
-                                                       surefireArtifact.getBaseVersion(), null );
+            return dependencyResolver.getProviderClasspath( "surefire-junit3", surefireArtifact.getBaseVersion(),
+                                                            null );
+
+        }
 
+        public Classpath getTestframeworkClasspath()
+        {
+            return junitArtifact != null ? new Classpath( junitArtifact.getFile() ) : new Classpath();
         }
 
+
     }
 
+
     class JUnit4ProviderInfo
-        implements ProviderInfo
+        extends JUnit4Provider
     {
-        private final Artifact junitArtifact;
-
-        private final Artifact junitDepArtifact;
-
         JUnit4ProviderInfo( Artifact junitArtifact, Artifact junitDepArtifact )
         {
-            this.junitArtifact = junitArtifact;
-            this.junitDepArtifact = junitDepArtifact;
+            super( junitArtifact, junitDepArtifact );
         }
 
         public String getProviderName()
@@ -1131,27 +1153,22 @@ public abstract class AbstractSurefireMo
         {
         }
 
-        public void addProviderArtifactToSurefireClasspath( ClasspathConfiguration classpathConfiguration )
+        public Classpath getProviderClasspath()
             throws ArtifactResolutionException, ArtifactNotFoundException
         {
-            dependencyResolver.addProviderToClasspath( classpathConfiguration, "surefire-junit4",
-                                                       surefireArtifact.getBaseVersion(), null );
+            return dependencyResolver.getProviderClasspath( "surefire-junit4", surefireArtifact.getBaseVersion(),
+                                                            null );
 
         }
 
     }
 
     class JUnitCoreProviderInfo
-        implements ProviderInfo
+        extends JUnit4Provider
     {
-        private final Artifact junitArtifact;
-
-        private final Artifact junitDepArtifact;
-
         JUnitCoreProviderInfo( Artifact junitArtifact, Artifact junitDepArtifact )
         {
-            this.junitArtifact = junitArtifact;
-            this.junitDepArtifact = junitDepArtifact;
+            super( junitArtifact, junitDepArtifact );
         }
 
         public String getProviderName()
@@ -1175,13 +1192,14 @@ public abstract class AbstractSurefireMo
             convertJunitCoreParameters();
         }
 
-        public void addProviderArtifactToSurefireClasspath( ClasspathConfiguration classpathConfiguration )
+        public Classpath getProviderClasspath()
             throws ArtifactResolutionException, ArtifactNotFoundException
         {
-            dependencyResolver.addProviderToClasspath( classpathConfiguration, "surefire-junit47",
-                                                       surefireArtifact.getBaseVersion(), null );
+            return dependencyResolver.getProviderClasspath( "surefire-junit47", surefireArtifact.getBaseVersion(),
+                                                            null );
         }
 
+
     }
 
     public class DynamicProviderInfo
@@ -1216,14 +1234,17 @@ public abstract class AbstractSurefireMo
             convertTestNGParameters();
         }
 
-        public void addProviderArtifactToSurefireClasspath( ClasspathConfiguration classpathConfiguration )
+        public Classpath getTestframeworkClasspath()
+        {
+            return new Classpath();
+        }
+
+        public Classpath getProviderClasspath()
             throws ArtifactResolutionException, ArtifactNotFoundException
         {
             final Map pluginArtifactMap = getPluginArtifactMap();
             Artifact plugin = (Artifact) pluginArtifactMap.get( "org.apache.maven.plugins:maven-surefire-plugin" );
-            dependencyResolver.addProviderToClasspath( classpathConfiguration, pluginArtifactMap, plugin );
+            return dependencyResolver.addProviderToClasspath( pluginArtifactMap, plugin );
         }
-
     }
-
 }

Modified: maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ProviderInfo.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ProviderInfo.java?rev=1071421&r1=1071420&r2=1071421&view=diff
==============================================================================
--- maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ProviderInfo.java (original)
+++ maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ProviderInfo.java Wed Feb 16 22:17:38 2011
@@ -21,18 +21,20 @@ package org.apache.maven.plugin.surefire
 
 import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
 import org.apache.maven.artifact.resolver.ArtifactResolutionException;
-import org.apache.maven.surefire.booter.ClasspathConfiguration;
+import org.apache.maven.surefire.booter.Classpath;
 
 /**
-* @author Kristian Rosenvold
-*/
+ * @author Kristian Rosenvold
+ */
 public interface ProviderInfo
 {
     String getProviderName();
 
     boolean isApplicable();
 
-    void addProviderArtifactToSurefireClasspath( ClasspathConfiguration bootclasspath )
+    Classpath getTestframeworkClasspath();
+
+    Classpath getProviderClasspath()
         throws ArtifactResolutionException, ArtifactNotFoundException;
 
     void addProviderProperties();

Modified: 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=1071421&r1=1071420&r2=1071421&view=diff
==============================================================================
--- maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireDependencyResolver.java (original)
+++ maven/surefire/trunk/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireDependencyResolver.java Wed Feb 16 22:17:38 2011
@@ -35,8 +35,8 @@ import org.apache.maven.artifact.version
 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.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.LinkedHashSet;
@@ -151,14 +151,14 @@ public class SurefireDependencyResolver
                                                      filter );
     }
 
-    public void addProviderToClasspath( ClasspathConfiguration classpathConfiguration, String provider, String version,
-                                        Artifact filteredArtifact )
+    public Classpath getProviderClasspath( 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 );
+        List files = new ArrayList();
 
         for ( Iterator i = result.getArtifacts().iterator(); i.hasNext(); )
         {
@@ -168,30 +168,15 @@ public class SurefireDependencyResolver
                 "Adding to " + pluginName + " test classpath: " + artifact.getFile().getAbsolutePath() + " Scope: "
                     + artifact.getScope() );
 
-            classpathConfiguration.addSurefireClasspathUrl( artifact.getFile().getAbsolutePath() );
+            files.add( artifact.getFile().getAbsolutePath() );
         }
+        return new Classpath( files );
     }
 
-    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() );
-        }
-    }
-
-    public void addProviderToClasspath( ClasspathConfiguration classpathConfiguration, Map pluginArtifactMap,
-                                        Artifact surefireArtifact )
+    public Classpath addProviderToClasspath( Map pluginArtifactMap, Artifact surefireArtifact )
         throws ArtifactResolutionException, ArtifactNotFoundException
     {
+        List files = new ArrayList();
         if ( surefireArtifact != null )
         {
             final ArtifactResolutionResult artifactResolutionResult = resolveArtifact( null, surefireArtifact );
@@ -200,7 +185,7 @@ public class SurefireDependencyResolver
                 Artifact artifact = (Artifact) iterator.next();
                 if ( !artifactResolutionResult.getArtifacts().contains( artifact ) )
                 {
-                    classpathConfiguration.addClasspathUrl( artifact.getFile().getPath() );
+                    files.add( artifact.getFile().getAbsolutePath() );
                 }
             }
         }
@@ -210,8 +195,25 @@ public class SurefireDependencyResolver
             for ( Iterator iterator = pluginArtifactMap.values().iterator(); iterator.hasNext(); )
             {
                 Artifact artifact = (Artifact) iterator.next();
-                classpathConfiguration.addClasspathUrl( artifact.getFile().getPath() );
+                files.add( artifact.getFile().getPath() );
             }
         }
+        return new Classpath( files );
     }
+
+    public Classpath getResolvedArtifactClasspath( Artifact surefireArtifact )
+        throws ArtifactNotFoundException, ArtifactResolutionException
+    {
+        ArtifactResolutionResult result = resolveArtifact( null, surefireArtifact );
+        List classpath = new ArrayList();
+
+        for ( Iterator i = result.getArtifacts().iterator(); i.hasNext(); )
+        {
+            Artifact artifact = (Artifact) i.next();
+
+            classpath.add( artifact.getFile().getAbsolutePath() );
+        }
+        return new Classpath( classpath);
+    }
+
 }

Modified: maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java?rev=1071421&r1=1071420&r2=1071421&view=diff
==============================================================================
--- maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java (original)
+++ maven/surefire/trunk/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java Wed Feb 16 22:17:38 2011
@@ -19,19 +19,10 @@ package org.apache.maven.plugin.surefire
  * under the License.
  */
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Properties;
-
-import junit.framework.TestCase;
-
 import org.apache.maven.surefire.booter.BooterConstants;
 import org.apache.maven.surefire.booter.BooterDeserializer;
 import org.apache.maven.surefire.booter.ClassLoaderConfiguration;
+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.StartupConfiguration;
@@ -41,6 +32,16 @@ import org.apache.maven.surefire.testset
 import org.apache.maven.surefire.testset.TestArtifactInfo;
 import org.apache.maven.surefire.testset.TestRequest;
 
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Properties;
+
+import junit.framework.TestCase;
+
 /**
  * Performs roundtrip testing of serialization/deserialization of The StartupConfiguration
  *
@@ -71,10 +72,10 @@ public class BooterDeserializerStartupCo
         assertEquals( "true", props.get( BooterConstants.ENABLE_ASSERTIONS ) );
         assertEquals( "true", props.get( BooterConstants.CHILD_DELEGATION ) );
         assertEquals( 2, testClassPathUrls.size() );
-        assertEquals( "CP1", testClassPathUrls.get( 0 ) );
-        assertEquals( "CP2", testClassPathUrls.get( 1 ) );
-        assertEquals( "SP1", props.get( BooterConstants.SUREFIRE_CLASSPATHURL + "0" ) );
-        assertEquals( "SP2", props.get( BooterConstants.SUREFIRE_CLASSPATHURL + "1" ) );
+        assertEquals( "T1", testClassPathUrls.get( 0 ) );
+        assertEquals( "T2", testClassPathUrls.get( 1 ) );
+        assertEquals( "P1", props.get( BooterConstants.SUREFIRE_CLASSPATHURL + "0" ) );
+        assertEquals( "P2", props.get( BooterConstants.SUREFIRE_CLASSPATHURL + "1" ) );
     }
 
     public void testClassLoaderConfiguration()
@@ -144,11 +145,11 @@ public class BooterDeserializerStartupCo
 
     private StartupConfiguration getTestStartupConfiguration( ClassLoaderConfiguration classLoaderConfiguration )
     {
-        ClasspathConfiguration classpathConfiguration = new ClasspathConfiguration( true, true );
-        classpathConfiguration.addClasspathUrl( "CP1" );
-        classpathConfiguration.addClasspathUrl( "CP2" );
-        classpathConfiguration.addSurefireClasspathUrl( "SP1" );
-        classpathConfiguration.addSurefireClasspathUrl( "SP2" );
+        Classpath testClasspath = new Classpath( Arrays.asList( new String[]{ "T1", "T2" } ) );
+        Classpath providerClasspath = new Classpath( Arrays.asList( new String[]{ "P1", "P2" } ) );
+        Classpath testFrameworkClasspath = new Classpath();
+        ClasspathConfiguration classpathConfiguration =
+            new ClasspathConfiguration( testClasspath, providerClasspath, testFrameworkClasspath, true, true );
         return new StartupConfiguration( "com.provider", classpathConfiguration, classLoaderConfiguration, false, false,
                                          false );
     }

Modified: maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterConstants.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterConstants.java?rev=1071421&r1=1071420&r2=1071421&view=diff
==============================================================================
--- maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterConstants.java (original)
+++ maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterConstants.java Wed Feb 16 22:17:38 2011
@@ -36,6 +36,7 @@ public interface BooterConstants
     String TYPES_SUFIX = ".types";
     String CLASSPATH_URL = "classPathUrl.";
     String SUREFIRE_CLASSPATHURL = "surefireClassPathUrl.";
+    String TEST_FRAMEWORK_CLASSPATHURL = "testFwClassPathUrl.";
     String CHILD_DELEGATION = "childDelegation";
     String ENABLE_ASSERTIONS = "enableAssertions";
     String USESYSTEMCLASSLOADER = "useSystemClassLoader";

Modified: maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterDeserializer.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterDeserializer.java?rev=1071421&r1=1071420&r2=1071421&view=diff
==============================================================================
--- maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterDeserializer.java (original)
+++ maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterDeserializer.java Wed Feb 16 22:17:38 2011
@@ -103,12 +103,13 @@ public class BooterDeserializer
 
         Classpath classpath = Classpath.readFromForkProperties( properties, CLASSPATH_URL );
         Classpath sureFireClasspath = Classpath.readFromForkProperties( properties, SUREFIRE_CLASSPATHURL );
+        Classpath testFrameworkClasspath = Classpath.readFromForkProperties( properties, TEST_FRAMEWORK_CLASSPATHURL );
 
         ClassLoaderConfiguration classLoaderConfiguration =
             new ClassLoaderConfiguration( useSystemClassLoader, useManifestOnlyJar );
 
         ClasspathConfiguration classpathConfiguration =
-            new ClasspathConfiguration( classpath, sureFireClasspath, enableAssertions, childDelegation );
+            new ClasspathConfiguration( classpath, sureFireClasspath, testFrameworkClasspath, enableAssertions, childDelegation );
 
         return StartupConfiguration.inForkedVm( providerConfiguration, classpathConfiguration,
                                                 classLoaderConfiguration );

Modified: maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/Classpath.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/Classpath.java?rev=1071421&r1=1071420&r2=1071421&view=diff
==============================================================================
--- maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/Classpath.java (original)
+++ maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/Classpath.java Wed Feb 16 22:17:38 2011
@@ -25,6 +25,7 @@ import java.io.File;
 import java.net.MalformedURLException;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Properties;
@@ -36,6 +37,14 @@ import java.util.Properties;
  */
 public class Classpath
 {
+    public Classpath( List files )
+    {
+        for ( Iterator iter = files.iterator(); iter.hasNext(); )
+        {
+            addClassPathElementUrl( (String) iter.next() );
+        }
+    }
+
     static Classpath readFromForkProperties( PropertiesWrapper properties, String prefix )
     {
         List elements = properties.getStringList( prefix );
@@ -44,10 +53,13 @@ public class Classpath
 
     public static Classpath join( Classpath firstClasspath, Classpath secondClasspath )
     {
-        Classpath joinedClasspath = new Classpath();
-        joinedClasspath.addElementsOfClasspath( firstClasspath );
-        joinedClasspath.addElementsOfClasspath( secondClasspath );
-        return joinedClasspath;
+
+        List result = new ArrayList( firstClasspath != null ? firstClasspath.elements : new ArrayList() );
+        if ( secondClasspath != null )
+        {
+            result.addAll( secondClasspath.elements );
+        }
+        return new Classpath( result );
     }
 
     private final List elements = new ArrayList();
@@ -56,13 +68,12 @@ public class Classpath
     {
     }
 
-    private Classpath( Collection elements )
+    public Classpath( File file )
     {
-        this();
-        addElements( elements );
+        this( Collections.singletonList( file.getAbsolutePath() ) );
     }
 
-    public void addClassPathElementUrl( String path )
+    void addClassPathElementUrl( String path )
     {
         if ( path == null )
         {
@@ -127,4 +138,9 @@ public class Classpath
         }
         System.setProperty( propertyName, sb.toString() );
     }
+
+    public int size()
+    {
+        return elements.size();
+    }
 }

Modified: maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ClasspathConfiguration.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ClasspathConfiguration.java?rev=1071421&r1=1071420&r2=1071421&view=diff
==============================================================================
--- maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ClasspathConfiguration.java (original)
+++ maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ClasspathConfiguration.java Wed Feb 16 22:17:38 2011
@@ -32,7 +32,7 @@ import java.util.Properties;
 /**
  * Represents the classpaths for the BooterConfiguration.
  * <p/>
- * 
+ *
  * @author Jason van Zyl
  * @author Emmanuel Venisse
  * @author Kristian Rosenvold
@@ -41,9 +41,11 @@ import java.util.Properties;
 public class ClasspathConfiguration
 {
 
-    private final Classpath classpathUrls;
+    private final Classpath testFrameworkClasspath;
 
-    private final Classpath surefireClasspathUrls;
+    private final Classpath testClasspath;
+
+    private final Classpath providerClasspath;
 
     /**
      * Whether to enable assertions or not (can be affected by the fork arguments, and the ability to do so based on the
@@ -56,25 +58,24 @@ public class ClasspathConfiguration
 
     public ClasspathConfiguration( boolean enableAssertions, boolean childDelegation )
     {
-        this( new Classpath(), new Classpath(), enableAssertions, childDelegation );
+        this( new Classpath(), new Classpath(), new Classpath(), enableAssertions, childDelegation );
     }
 
-    /*
-    * Reads the config from the supplied stream. Closes the stream.
-    */
-    public ClasspathConfiguration( Classpath classPathUrls, Classpath surefireClassPathUrls, boolean enableAssertions,
-                                   boolean childDelegation )
+    public ClasspathConfiguration( Classpath testClasspath, Classpath providerClasspath,
+                                   Classpath testFrameworkClasspath, boolean enableAssertions, boolean childDelegation )
     {
+        this.testFrameworkClasspath = testFrameworkClasspath;
+        this.testClasspath = testClasspath;
+        this.providerClasspath = providerClasspath;
         this.enableAssertions = enableAssertions;
         this.childDelegation = childDelegation;
-        this.classpathUrls = classPathUrls;
-        this.surefireClasspathUrls = surefireClassPathUrls;
     }
 
     public void setForkProperties( Properties properties )
     {
-        classpathUrls.writeToForkProperties( properties, BooterConstants.CLASSPATH_URL );
-        surefireClasspathUrls.writeToForkProperties( properties, BooterConstants.SUREFIRE_CLASSPATHURL );
+        testClasspath.writeToForkProperties( properties, BooterConstants.CLASSPATH_URL );
+        providerClasspath.writeToForkProperties( properties, BooterConstants.SUREFIRE_CLASSPATHURL );
+        testFrameworkClasspath.writeToForkProperties( properties, BooterConstants.TEST_FRAMEWORK_CLASSPATHURL );
         properties.setProperty( BooterConstants.ENABLE_ASSERTIONS, String.valueOf( enableAssertions ) );
         properties.setProperty( BooterConstants.CHILD_DELEGATION, String.valueOf( childDelegation ) );
     }
@@ -105,80 +106,112 @@ public class ClasspathConfiguration
     public ClassLoader createTestClassLoader( boolean childDelegation )
         throws SurefireExecutionException
     {
-        return createClassLoaderSEE( classpathUrls, null, childDelegation );
+        ClassLoader testFrameWorkClassLoader = createTestFrameworkClassLoader( childDelegation );
+        return createClassLoader( testClasspath, testFrameWorkClassLoader, childDelegation, "Test" );
+    }
+
+    private ClassLoader createTestFrameworkClassLoader( boolean childDelegation )
+        throws SurefireExecutionException
+    {
+        return hasTestFrameworkClasspath() ? createClassLoader( testFrameworkClasspath, null, childDelegation,
+                                                                "TestFramework" ) : null;
     }
 
     public ClassLoader createTestClassLoader()
         throws SurefireExecutionException
     {
-        return createClassLoaderSEE( classpathUrls, null, this.childDelegation );
+        final ClassLoader testFrameworkClassLoader = createTestFrameworkClassLoader( this.childDelegation );
+        return createClassLoader( testClasspath, testFrameworkClassLoader, this.childDelegation, "Test" );
     }
 
-    public ClassLoader createSurefireClassLoader( ClassLoader parent )
+    public ClassLoader createTestframeworkClassLoader()
         throws SurefireExecutionException
     {
-        return createClassLoaderSEE( surefireClasspathUrls, parent, false );
+        return createClassLoader( testFrameworkClasspath, null, this.childDelegation, "Test" );
     }
 
-    private ClassLoader createClassLoaderSEE( Classpath classPathUrls, ClassLoader parent, boolean childDelegation )
+    public ClassLoader createSurefireClassLoader( ClassLoader parent )
         throws SurefireExecutionException
     {
-        try
-        {
-            return createClassLoader( classPathUrls, parent, childDelegation );
-        }
-        catch ( MalformedURLException e )
-        {
-            throw new SurefireExecutionException( "When creating classloader", e );
-        }
+        boolean useTestClassLoaderAsParent =
+            parent.equals( ClassLoader.getSystemClassLoader() ) || !hasTestFrameworkClasspath();
 
+        ClassLoader parentToUse = useTestClassLoaderAsParent ? parent : parent.getParent();
+
+        return createClassLoader( providerClasspath, parentToUse, false, "Provider" );
     }
 
-    private ClassLoader createClassLoader( Classpath classPathUrls, ClassLoader parent, boolean childDelegation )
-        throws MalformedURLException
+    private ClassLoader createClassLoader( Classpath classPathUrls, ClassLoader parent, boolean childDelegation,
+                                           String description )
+        throws SurefireExecutionException
     {
-        List urls = classPathUrls.getAsUrlList();
-        IsolatedClassLoader classLoader = new IsolatedClassLoader( parent, childDelegation );
-        if ( assertionStatusMethod != null )
+        try
         {
-            try
+            List urls = classPathUrls.getAsUrlList();
+            IsolatedClassLoader classLoader = new IsolatedClassLoader( parent, childDelegation, description );
+            if ( assertionStatusMethod != null )
             {
-                Object[] args = new Object[]{ enableAssertions ? Boolean.TRUE : Boolean.FALSE };
-                if ( parent != null )
+                try
                 {
-                    assertionStatusMethod.invoke( parent, args );
+                    Object[] args = new Object[]{ enableAssertions ? Boolean.TRUE : Boolean.FALSE };
+                    if ( parent != null )
+                    {
+                        assertionStatusMethod.invoke( parent, args );
+                    }
+                    assertionStatusMethod.invoke( classLoader, args );
+                }
+                catch ( IllegalAccessException e )
+                {
+                    throw new NestedRuntimeException( "Unable to access the assertion enablement method", e );
+                }
+                catch ( InvocationTargetException e )
+                {
+                    throw new NestedRuntimeException( "Unable to invoke the assertion enablement method", e );
                 }
-                assertionStatusMethod.invoke( classLoader, args );
-            }
-            catch ( IllegalAccessException e )
-            {
-                throw new NestedRuntimeException( "Unable to access the assertion enablement method", e );
             }
-            catch ( InvocationTargetException e )
+            for ( Iterator iter = urls.iterator(); iter.hasNext(); )
             {
-                throw new NestedRuntimeException( "Unable to invoke the assertion enablement method", e );
+                URL url = (URL) iter.next();
+                classLoader.addURL( url );
             }
+            return classLoader;
         }
-        for ( Iterator iter = urls.iterator(); iter.hasNext(); )
+        catch ( MalformedURLException e )
         {
-            URL url = (URL) iter.next();
-            classLoader.addURL( url );
+            throw new SurefireExecutionException( "When creating classloader", e );
         }
-        return classLoader;
     }
 
     public Classpath getTestClasspath()
     {
-        return classpathUrls;
+        return testClasspath;
     }
 
     public void addClasspathUrl( String path )
     {
-        classpathUrls.addClassPathElementUrl( path );
+        testClasspath.addClassPathElementUrl( path );
     }
 
     public void addSurefireClasspathUrl( String path )
     {
-        surefireClasspathUrls.addClassPathElementUrl( path );
+        providerClasspath.addClassPathElementUrl( path );
     }
+
+    private Classpath getTestFrameworkClasspath()
+    {
+        return testFrameworkClasspath;
+    }
+
+    /**
+     * Indicates if there is a test framework classpath present, which triggers
+     * the pitchfork classloader configuration.
+     *
+     * @return True if there is a test framework classpath available
+     */
+    private boolean hasTestFrameworkClasspath()
+    {
+        return testFrameworkClasspath.size() > 0;
+    }
+
+
 }

Modified: maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java?rev=1071421&r1=1071420&r2=1071421&view=diff
==============================================================================
--- maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java (original)
+++ maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java Wed Feb 16 22:17:38 2011
@@ -29,7 +29,6 @@ import java.util.Properties;
  * <p/>
  * Deals with deserialization of the booter wire-level protocol
  * <p/>
- * Todo: Look at relationship between this class and BooterSerializer (BooterDeserializer?)
  *
  * @author Jason van Zyl
  * @author Emmanuel Venisse

Modified: maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/IsolatedClassLoader.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/IsolatedClassLoader.java?rev=1071421&r1=1071420&r2=1071421&view=diff
==============================================================================
--- maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/IsolatedClassLoader.java (original)
+++ maven/surefire/trunk/surefire-booter/src/main/java/org/apache/maven/surefire/booter/IsolatedClassLoader.java Wed Feb 16 22:17:38 2011
@@ -30,6 +30,9 @@ import java.util.Set;
 public class IsolatedClassLoader
     extends URLClassLoader
 {
+
+    private final String description;
+
     private final ClassLoader parent = ClassLoader.getSystemClassLoader();
 
     private final Set urls = new HashSet();
@@ -38,11 +41,13 @@ public class IsolatedClassLoader
 
     private static final URL[] EMPTY_URL_ARRAY = new URL[0];
 
-    public IsolatedClassLoader( ClassLoader parent, boolean childDelegation )
+    public IsolatedClassLoader( ClassLoader parent, boolean childDelegation, String description )
     {
         super( EMPTY_URL_ARRAY, parent );
 
         this.childDelegation = childDelegation;
+
+        this.description = description;
     }
 
     public void addURL( URL url )
@@ -95,4 +100,10 @@ public class IsolatedClassLoader
 
         return c;
     }
+
+
+    public String toString()
+    {
+        return description;
+    }
 }

Modified: maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreRunListener.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreRunListener.java?rev=1071421&r1=1071420&r2=1071421&view=diff
==============================================================================
--- maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreRunListener.java (original)
+++ maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreRunListener.java Wed Feb 16 22:17:38 2011
@@ -21,6 +21,7 @@ package org.apache.maven.surefire.junitc
 
 import org.apache.maven.surefire.common.junit4.JUnit4RunListener;
 import org.apache.maven.surefire.report.Reporter;
+import org.apache.maven.surefire.util.NestedRuntimeException;
 
 import java.util.ArrayList;
 import java.util.Map;
@@ -75,7 +76,16 @@ public class JUnitCoreRunListener
                 testSet.incrementTestMethodCount();
                 if ( itemTestClass == null )
                 {
-                    itemTestClass = item.getTestClass();
+                    String className = item.getClassName();
+                    try
+                    {
+                        itemTestClass = Class.forName( className);
+                    }
+                    catch ( ClassNotFoundException ignore )
+                    {
+                        throw new NestedRuntimeException( "Should not have trouble with this" , ignore );
+                    }
+
                 }
             }
             else if ( item.getChildren().size() > 0 )

Modified: maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/TestSet.java
URL: http://svn.apache.org/viewvc/maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/TestSet.java?rev=1071421&r1=1071420&r2=1071421&view=diff
==============================================================================
--- maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/TestSet.java (original)
+++ maven/surefire/trunk/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/TestSet.java Wed Feb 16 22:17:38 2011
@@ -23,6 +23,7 @@ import org.apache.maven.surefire.report.
 import org.apache.maven.surefire.report.ReportWriter;
 import org.apache.maven.surefire.report.Reporter;
 import org.apache.maven.surefire.report.SimpleReportEntry;
+import org.apache.maven.surefire.util.NestedRuntimeException;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -30,7 +31,6 @@ import java.util.List;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 
-import org.apache.maven.surefire.util.NestedRuntimeException;
 import org.junit.runner.Description;
 
 /**
@@ -102,7 +102,7 @@ public class TestSet
 
     private ReportEntry createReportEntry( Integer elapsed )
     {
-        boolean isJunit3 = testSetDescription.getTestClass() == null;
+        boolean isJunit3 = testSetDescription.getClassName() == null;
         String classNameToUse =
             isJunit3 ? testSetDescription.getChildren().get( 0 ).getClassName() : testSetDescription.getClassName();
         return new SimpleReportEntry( classNameToUse, classNameToUse, elapsed );