You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by ke...@apache.org on 2006/12/19 03:38:10 UTC
svn commit: r488508 - in /maven/sandbox/surefire-plugin-merge:
maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/
surefire-booter/
surefire-booter/src/main/java/org/apache/maven/surefire/booter/
Author: kenney
Date: Mon Dec 18 18:38:09 2006
New Revision: 488508
URL: http://svn.apache.org/viewvc?view=rev&rev=488508
Log:
PR: MSUREFIRE-115, MSUREFIRE-121
Add boolean parameter 'useSystemClassLoader', used when forking tests, to put all tests
in the System classloader.
I also found a nice way to circumvent the possibly long commandline arguments when specifying
all classpath elements (and dependencies) at the '-classpath' parameter: I create an empty
uncompressed jar with a Main-Class attribute for SurefireBooter and a Class-Path entry containing
all the classpath elements. The fork is then done using 'java -jar'.
I do NOT allow a partial classpath to be specified with -classpath since that either requires
duplicate classpath entries, or all dependencies to be specified on the commandline too.
Modified:
maven/sandbox/surefire-plugin-merge/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
maven/sandbox/surefire-plugin-merge/surefire-booter/pom.xml
maven/sandbox/surefire-plugin-merge/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkConfiguration.java
maven/sandbox/surefire-plugin-merge/surefire-booter/src/main/java/org/apache/maven/surefire/booter/SurefireBooter.java
Modified: maven/sandbox/surefire-plugin-merge/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
URL: http://svn.apache.org/viewvc/maven/sandbox/surefire-plugin-merge/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java?view=diff&rev=488508&r1=488507&r2=488508
==============================================================================
--- maven/sandbox/surefire-plugin-merge/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java (original)
+++ maven/sandbox/surefire-plugin-merge/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java Mon Dec 18 18:38:09 2006
@@ -98,6 +98,7 @@
*/
private File basedir;
+ // FIXME this field is not used
/**
* The directory containing generated classes of the project being tested.
*
@@ -373,27 +374,20 @@
*/
private boolean disableXmlReport;
+ /**
+ * Option to pass dependencies to the system's classloader instead of using an isolated class loader when
+ * forking. Prevents problems with JDKs which implement the service provider lookup mechanism by using
+ * the system's classloader.
+ *
+ * @parameter expression="${surefire.useSystemClassLoader}" default-value="false"
+ */
+ private boolean useSystemClassLoader;
+
public void execute()
throws MojoExecutionException, MojoFailureException
{
- if ( skip || skipExec )
- {
- getLog().info( "Tests are skipped." );
- }
- else if ( !testClassesDirectory.exists() )
- {
- getLog().info( "No tests to run." );
- }
- else
+ if ( verifyParameters() )
{
- if ( parallel )
- {
- if ( threadCount < 1 )
- {
- throw new MojoFailureException( "Must have at least one thread in parallel mode" );
- }
- }
-
SurefireBooter surefireBooter = constructSurefireBooter();
getLog().info( "Surefire report directory: " + reportsDirectory );
@@ -434,6 +428,36 @@
}
}
+ private boolean verifyParameters()
+ throws MojoFailureException
+ {
+ if ( skip || skipExec )
+ {
+ getLog().info( "Tests are skipped." );
+ return false;
+ }
+ else if ( !testClassesDirectory.exists() )
+ {
+ getLog().info( "No tests to run." );
+ return false;
+ }
+
+ if ( parallel )
+ {
+ if ( threadCount < 1 )
+ {
+ throw new MojoFailureException( "Must have at least one thread in parallel mode" );
+ }
+ }
+
+ if ( useSystemClassLoader && ForkConfiguration.FORK_NEVER.equals( forkMode ) )
+ {
+ getLog().warn( "useSystemClassloader=true setting has no effect when not forking" );
+ }
+
+ return true;
+ }
+
private SurefireBooter constructSurefireBooter()
throws MojoExecutionException, MojoFailureException
{
@@ -646,6 +670,8 @@
surefireBooter.setChildDelegation( childDelegation );
surefireBooter.setReportsDirectory( reportsDirectory );
+
+ surefireBooter.setUseSystemClassLoader( useSystemClassLoader );
addReporters( surefireBooter, fork.isForking() );
Modified: maven/sandbox/surefire-plugin-merge/surefire-booter/pom.xml
URL: http://svn.apache.org/viewvc/maven/sandbox/surefire-plugin-merge/surefire-booter/pom.xml?view=diff&rev=488508&r1=488507&r2=488508
==============================================================================
--- maven/sandbox/surefire-plugin-merge/surefire-booter/pom.xml (original)
+++ maven/sandbox/surefire-plugin-merge/surefire-booter/pom.xml Mon Dec 18 18:38:09 2006
@@ -33,6 +33,17 @@
<version>${project.version}</version>
</dependency>
<dependency>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-archiver</artifactId>
+ <version>1.0-alpha-7</version>
+ <exclusions> <!-- exclude plexus-utils since it's 1.2 and we need 1.1 -->
+ <exclusion>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-utils</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
Modified: maven/sandbox/surefire-plugin-merge/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkConfiguration.java
URL: http://svn.apache.org/viewvc/maven/sandbox/surefire-plugin-merge/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkConfiguration.java?view=diff&rev=488508&r1=488507&r2=488508
==============================================================================
--- maven/sandbox/surefire-plugin-merge/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkConfiguration.java (original)
+++ maven/sandbox/surefire-plugin-merge/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkConfiguration.java Mon Dec 18 18:38:09 2006
@@ -16,9 +16,14 @@
* limitations under the License.
*/
+import org.codehaus.plexus.archiver.ArchiverException;
+import org.codehaus.plexus.archiver.jar.JarArchiver;
+import org.codehaus.plexus.archiver.jar.Manifest;
+import org.codehaus.plexus.archiver.jar.ManifestException;
import org.codehaus.plexus.util.StringUtils;
import java.io.File;
+import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -29,6 +34,7 @@
* Configuration for forking tests.
*
* @author <a href="mailto:brett@apache.org">Brett Porter</a>
+ * @author <a href="mailto:kenney@apache.org">Kenney Westerhof</a>
*/
public class ForkConfiguration
{
@@ -112,7 +118,18 @@
return systemProperties;
}
+ /**
+ * @throws SurefireBooterForkException
+ * @deprecated use the 2-arg alternative.
+ */
public Commandline createCommandLine( List classPath )
+ throws SurefireBooterForkException
+ {
+ return createCommandLine( classPath, false );
+ }
+
+ public Commandline createCommandLine( List classPath, boolean useJar )
+ throws SurefireBooterForkException
{
Commandline cli = new Commandline();
@@ -143,15 +160,84 @@
"-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005" );
}
- cli.createArgument().setValue( "-classpath" );
+ if ( useJar )
+ {
+ File jarFile;
+ try
+ {
+ jarFile = createJar( classPath );
+ }
+ catch ( IOException e )
+ {
+ throw new SurefireBooterForkException( "Error creating archive file", e );
+ }
+ catch ( ManifestException e )
+ {
+ throw new SurefireBooterForkException( "Error creating manifest", e );
+ }
+ catch ( ArchiverException e )
+ {
+ throw new SurefireBooterForkException( "Error creating archive", e );
+ }
+
+ cli.createArgument().setValue( "-jar" );
+
+ cli.createArgument().setValue( jarFile.getAbsolutePath() );
+ }
+ else
+ {
+ cli.createArgument().setValue( "-classpath" );
- cli.createArgument().setValue( StringUtils.join( classPath.iterator(), File.pathSeparator ) );
+ cli.createArgument().setValue( StringUtils.join( classPath.iterator(), File.pathSeparator ) );
- cli.createArgument().setValue( SurefireBooter.class.getName() );
+ cli.createArgument().setValue( SurefireBooter.class.getName() );
+ }
cli.setWorkingDirectory( workingDirectory.getAbsolutePath() );
return cli;
+ }
+
+ /**
+ * Create a jar with just a manifest containing a Main-Class entry for SurefireBooter and a Class-Path entry
+ * for all classpath elements.
+ * @param classPath List<String> of all classpath elements.
+ * @return
+ * @throws IOException
+ * @throws ManifestException
+ * @throws ArchiverException
+ */
+ private static File createJar( List classPath )
+ throws IOException, ManifestException, ArchiverException
+ {
+ JarArchiver jar = new JarArchiver();
+ jar.setCompress( false ); // for speed
+ File file = File.createTempFile( "surefirebooter", ".jar" );
+ file.deleteOnExit();
+ jar.setDestFile( file );
+
+ Manifest manifest = new Manifest();
+
+ // we can't use StringUtils.join here since we need to add a '/' to
+ // the end of directory entries - otherwise the jvm will ignore them.
+ String cp = "";
+ for ( Iterator it = classPath.iterator(); it.hasNext(); )
+ {
+ String el = (String) it.next();
+ cp += " " + el + ( new File( el ).isDirectory() ? "/" : "" );
+ }
+
+ Manifest.Attribute attr = new Manifest.Attribute( "Class-Path", cp.trim() );
+ manifest.addConfiguredAttribute( attr );
+
+ attr =new Manifest.Attribute("Main-Class", SurefireBooter.class.getName() );
+ manifest.addConfiguredAttribute( attr );
+
+ jar.addConfiguredManifest( manifest );
+
+ jar.createArchive();
+
+ return file;
}
public void setDebug( boolean debug )
Modified: maven/sandbox/surefire-plugin-merge/surefire-booter/src/main/java/org/apache/maven/surefire/booter/SurefireBooter.java
URL: http://svn.apache.org/viewvc/maven/sandbox/surefire-plugin-merge/surefire-booter/src/main/java/org/apache/maven/surefire/booter/SurefireBooter.java?view=diff&rev=488508&r1=488507&r2=488508
==============================================================================
--- maven/sandbox/surefire-plugin-merge/surefire-booter/src/main/java/org/apache/maven/surefire/booter/SurefireBooter.java (original)
+++ maven/sandbox/surefire-plugin-merge/surefire-booter/src/main/java/org/apache/maven/surefire/booter/SurefireBooter.java Mon Dec 18 18:38:09 2006
@@ -68,6 +68,8 @@
private boolean redirectTestOutputToFile = false;
+ private boolean useSystemClassLoader = false;
+
// ----------------------------------------------------------------------
//
// ----------------------------------------------------------------------
@@ -176,6 +178,11 @@
this.forkConfiguration = forkConfiguration;
}
+ public void setUseSystemClassLoader( boolean useSystemClassLoader )
+ {
+ this.useSystemClassLoader = useSystemClassLoader;
+ }
+
public boolean run()
throws SurefireBooterForkException, SurefireExecutionException
{
@@ -214,7 +221,9 @@
ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader();
try
{
- ClassLoader testsClassLoader = createClassLoader( classPathUrls, null, childDelegation, true );
+ ClassLoader testsClassLoader = useSystemClassLoader
+ ? ClassLoader.getSystemClassLoader()
+ : createClassLoader( classPathUrls, null, childDelegation, true );
// TODO: assertions = true shouldn't be required for this CL if we had proper separation (see TestNG)
ClassLoader surefireClassLoader =
@@ -242,7 +251,7 @@
{
throw new SurefireExecutionException( "Unable to instantiate and execute Surefire", e );
}
- finally
+ finally
{
Thread.currentThread().setContextClassLoader( oldContextClassLoader );
}
@@ -255,12 +264,14 @@
//noinspection CatchGenericClass,OverlyBroadCatchBlock
ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader();
-
+
try
{
// The test classloader must be constructed first to avoid issues with commons-logging until we properly
// separate the TestNG classloader
- ClassLoader testsClassLoader = createClassLoader( classPathUrls, null, childDelegation, true );
+ ClassLoader testsClassLoader = useSystemClassLoader
+ ? getClass().getClassLoader()//ClassLoader.getSystemClassLoader()
+ : createClassLoader( classPathUrls, null, childDelegation, true );
ClassLoader surefireClassLoader =
createClassLoader( surefireClassPathUrls, testsClassLoader, true );
@@ -272,7 +283,6 @@
Method run = surefireClass.getMethod( "run", new Class[]{List.class, List.class, ClassLoader.class,
ClassLoader.class} );
-
Thread.currentThread().setContextClassLoader( testsClassLoader );
Boolean result = (Boolean) run.invoke( surefire, new Object[]{reports, testSuites, surefireClassLoader,
@@ -288,7 +298,7 @@
{
throw new SurefireExecutionException( "Unable to instantiate and execute Surefire", e );
}
- finally
+ finally
{
Thread.currentThread().setContextClassLoader( oldContextClassLoader );
}
@@ -416,7 +426,7 @@
addPropertiesForTypeHolder( reports, properties, "report." );
addPropertiesForTypeHolder( testSuites, properties, "testSuite." );
- for ( int i = 0; i < classPathUrls.size(); i++ )
+ for ( int i = 0; i < classPathUrls.size() && !useSystemClassLoader; i++ )
{
String url = (String) classPathUrls.get( i );
properties.setProperty( "classPathUrl." + i, url );
@@ -428,13 +438,8 @@
properties.setProperty( "surefireClassPathUrl." + i, url );
}
- for ( int i = 0; i < surefireBootClassPathUrls.size(); i++ )
- {
- String url = (String) surefireBootClassPathUrls.get( i );
- properties.setProperty( "surefireBootClassPathUrl." + i, url );
- }
-
properties.setProperty( "childDelegation", String.valueOf( childDelegation ) );
+ properties.setProperty( "useSystemClassLoader", String.valueOf( useSystemClassLoader ) );
}
private File writePropertiesFile( String name, Properties properties )
@@ -512,7 +517,16 @@
throw new SurefireBooterForkException( "Error creating properties files for forking", e );
}
- Commandline cli = forkConfiguration.createCommandLine( surefireBootClassPathUrls );
+ List bootClasspath = new ArrayList( surefireBootClassPathUrls.size() + classPathUrls.size() );
+
+ bootClasspath.addAll( surefireBootClassPathUrls );
+
+ if ( useSystemClassLoader )
+ {
+ bootClasspath.addAll( classPathUrls );
+ }
+
+ Commandline cli = forkConfiguration.createCommandLine( bootClasspath, useSystemClassLoader );
cli.createArgument().setFile( surefireProperties );
@@ -783,6 +797,11 @@
{
surefireBooter.childDelegation =
Boolean.valueOf( p.getProperty( "childDelegation" ) ).booleanValue();
+ }
+ else if ( "useSystemClassLoader".equals( name ) )
+ {
+ surefireBooter.useSystemClassLoader =
+ Boolean.valueOf( p.getProperty( "useSystemClassLoader" ) ).booleanValue();
}
}