You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by ti...@apache.org on 2017/11/19 08:14:30 UTC
[3/4] maven-surefire git commit: [SUREFIRE-1262] Add modulepath
support
[SUREFIRE-1262] Add modulepath support
Project: http://git-wip-us.apache.org/repos/asf/maven-surefire/repo
Commit: http://git-wip-us.apache.org/repos/asf/maven-surefire/commit/f337881f
Tree: http://git-wip-us.apache.org/repos/asf/maven-surefire/tree/f337881f
Diff: http://git-wip-us.apache.org/repos/asf/maven-surefire/diff/f337881f
Branch: refs/heads/master
Commit: f337881ff7f47ab35669d9c499213f5a6b9a4d8b
Parents: 660a4cf
Author: Tibor17 <ti...@apache.org>
Authored: Fri Nov 17 15:09:52 2017 +0100
Committer: Tibor17 <ti...@apache.org>
Committed: Sun Nov 19 01:56:51 2017 +0100
----------------------------------------------------------------------
maven-surefire-common/pom.xml | 27 +-
.../plugin/surefire/AbstractSurefireMojo.java | 271 ++++++--
.../surefire/InPluginVMSurefireStarter.java | 5 +-
.../AbstractClasspathForkConfiguration.java | 73 +++
.../surefire/booterclient/BooterSerializer.java | 94 +--
.../ClasspathForkConfiguration.java | 59 ++
.../booterclient/DefaultForkConfiguration.java | 343 ++++++++++
.../booterclient/ForkConfiguration.java | 367 +----------
.../surefire/booterclient/ForkStarter.java | 27 +-
.../JarManifestForkConfiguration.java | 139 ++++
.../ModularClasspathForkConfiguration.java | 230 +++++++
.../plugin/surefire/booterclient/Platform.java | 29 +-
.../maven/plugin/surefire/util/Relocator.java | 39 +-
.../surefire/providerapi/ServiceLoader.java | 2 +-
.../surefire/AbstractSurefireMojoTest.java | 641 ++++++++++++++++++-
...terDeserializerStartupConfigurationTest.java | 8 +-
.../DefaultForkConfigurationTest.java | 319 +++++++++
.../booterclient/ForkConfigurationTest.java | 52 +-
.../apache/maven/surefire/JUnit4SuiteTest.java | 4 +-
.../maven/surefire/util/RelocatorTest.java | 6 +-
.../plugin/surefire/SurefirePluginTest.java | 3 +-
pom.xml | 65 +-
.../maven/surefire/util/DefaultScanResult.java | 24 +-
.../maven/surefire/util/ScanResultTest.java | 8 +-
.../booter/AbstractPathConfiguration.java | 115 ++++
.../apache/maven/surefire/booter/Classpath.java | 19 +-
.../surefire/booter/ClasspathConfiguration.java | 73 +--
.../maven/surefire/booter/ForkedBooter.java | 22 +-
.../maven/surefire/booter/ModularClasspath.java | 70 ++
.../booter/ModularClasspathConfiguration.java | 62 ++
.../surefire/booter/StartupConfiguration.java | 28 +-
.../maven/surefire/booter/SystemUtilsTest.java | 5 +-
.../apache/maven/surefire/its/ModulePathIT.java | 45 ++
.../src/test/resources/modulepath/pom.xml | 45 ++
.../modulepath/src/main/java/com/app/Main.java | 34 +
.../modulepath/src/main/java/module-info.java | 21 +
.../src/test/java/com/app/AppTest.java | 36 ++
37 files changed, 2759 insertions(+), 651 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/f337881f/maven-surefire-common/pom.xml
----------------------------------------------------------------------
diff --git a/maven-surefire-common/pom.xml b/maven-surefire-common/pom.xml
index 1bcd7c5..7e063c8 100644
--- a/maven-surefire-common/pom.xml
+++ b/maven-surefire-common/pom.xml
@@ -97,25 +97,36 @@
<dependency>
<groupId>org.apache.maven.shared</groupId>
<artifactId>maven-common-artifact-filters</artifactId>
- <version>1.3</version>
- <exclusions>
- <exclusion>
- <groupId>org.apache.maven.shared</groupId>
- <artifactId>maven-plugin-testing-harness</artifactId>
- </exclusion>
- </exclusions>
</dependency>
<dependency>
<groupId>org.fusesource.jansi</groupId>
<artifactId>jansi</artifactId>
- <version>1.13</version>
<scope>provided</scope>
</dependency>
<dependency>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-java</artifactId>
+ </dependency>
+ <dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito2</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/f337881f/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
index 7aa1e37..16b59ca 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
@@ -24,6 +24,7 @@ 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.AbstractArtifactResolutionException;
import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
@@ -43,6 +44,9 @@ import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.apache.maven.plugin.surefire.booterclient.ChecksumCalculator;
import org.apache.maven.plugin.surefire.booterclient.ForkConfiguration;
import org.apache.maven.plugin.surefire.booterclient.ForkStarter;
+import org.apache.maven.plugin.surefire.booterclient.ClasspathForkConfiguration;
+import org.apache.maven.plugin.surefire.booterclient.JarManifestForkConfiguration;
+import org.apache.maven.plugin.surefire.booterclient.ModularClasspathForkConfiguration;
import org.apache.maven.plugin.surefire.booterclient.Platform;
import org.apache.maven.plugin.surefire.booterclient.ProviderDetector;
import org.apache.maven.plugin.surefire.log.PluginConsoleLogger;
@@ -58,6 +62,8 @@ 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.KeyValueSource;
+import org.apache.maven.surefire.booter.ModularClasspath;
+import org.apache.maven.surefire.booter.ModularClasspathConfiguration;
import org.apache.maven.surefire.booter.ProviderConfiguration;
import org.apache.maven.surefire.booter.ProviderParameterNames;
import org.apache.maven.surefire.booter.Shutdown;
@@ -81,6 +87,9 @@ import org.apache.maven.toolchain.DefaultToolchain;
import org.apache.maven.toolchain.Toolchain;
import org.apache.maven.toolchain.ToolchainManager;
import org.codehaus.plexus.logging.Logger;
+import org.codehaus.plexus.languages.java.jpms.LocationManager;
+import org.codehaus.plexus.languages.java.jpms.ResolvePathsRequest;
+import org.codehaus.plexus.languages.java.jpms.ResolvePathsResult;
import javax.annotation.Nonnull;
import java.io.File;
@@ -88,7 +97,6 @@ import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
@@ -99,13 +107,18 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import static java.lang.Thread.currentThread;
+import static java.util.Arrays.asList;
+import static java.util.Collections.addAll;
import static java.util.Collections.singletonMap;
import static org.apache.commons.lang3.JavaVersion.JAVA_1_7;
import static org.apache.commons.lang3.JavaVersion.JAVA_9;
import static org.apache.commons.lang3.JavaVersion.JAVA_RECENT;
+import static org.apache.commons.lang3.StringUtils.substringBeforeLast;
import static org.apache.commons.lang3.SystemUtils.IS_OS_WINDOWS;
import static org.apache.commons.lang3.SystemUtils.isJavaVersionAtLeast;
import static org.apache.maven.shared.utils.StringUtils.capitalizeFirstLetter;
@@ -133,12 +146,13 @@ public abstract class AbstractSurefireMojo
extends AbstractMojo
implements SurefireExecutionParameters
{
+ private static final String FORK_ONCE = "once";
+ private static final String FORK_ALWAYS = "always";
+ private static final String FORK_NEVER = "never";
+ private static final String FORK_PERTHREAD = "perthread";
private static final Map<String, String> JAVA_9_MATCHER_OLD_NOTATION = singletonMap( "version", "[1.9,)" );
-
private static final Map<String, String> JAVA_9_MATCHER = singletonMap( "version", "[9,)" );
-
private static final Platform PLATFORM = new Platform();
-
private static final File SYSTEM_TMP_DIR = new File( System.getProperty( "java.io.tmpdir" ) );
private final ProviderDetector providerDetector = new ProviderDetector();
@@ -731,6 +745,9 @@ public abstract class AbstractSurefireMojo
@Component
private ToolchainManager toolchainManager;
+ @Component
+ private LocationManager locationManager;
+
private Artifact surefireBooterArtifact;
private Toolchain toolchain;
@@ -887,7 +904,7 @@ public abstract class AbstractSurefireMojo
// @TODO noinspection unchecked, check MavenProject 3.x for Generics in surefire:3.0
@SuppressWarnings( "unchecked" )
List<File> dependenciesToScan =
- DependencyScanner.filter( project.getTestArtifacts(), Arrays.asList( getDependenciesToScan() ) );
+ DependencyScanner.filter( project.getTestArtifacts(), asList( getDependenciesToScan() ) );
DependencyScanner scanner = new DependencyScanner( dependenciesToScan, getIncludedAndExcludedTests() );
return scanner.scan();
}
@@ -1107,7 +1124,7 @@ public abstract class AbstractSurefireMojo
createCopyAndReplaceForkNumPlaceholder( effectiveProperties, 1 ).copyToSystemProperties();
InPluginVMSurefireStarter surefireStarter =
- createInprocessStarter( provider, classLoaderConfiguration, runOrderParameters );
+ createInprocessStarter( provider, classLoaderConfiguration, runOrderParameters, scanResult );
return surefireStarter.runSuitesInProcess( scanResult );
}
else
@@ -1123,7 +1140,7 @@ public abstract class AbstractSurefireMojo
try
{
forkStarter = createForkStarter( provider, forkConfiguration, classLoaderConfiguration,
- runOrderParameters, getConsoleLogger() );
+ runOrderParameters, getConsoleLogger(), scanResult );
return forkStarter.run( effectiveProperties, scanResult );
}
@@ -1199,6 +1216,16 @@ public abstract class AbstractSurefireMojo
return tc;
}
+ private boolean existsModuleDescriptor()
+ {
+ return getModuleDescriptor().isFile();
+ }
+
+ private File getModuleDescriptor()
+ {
+ return new File( getClassesDirectory(), "module-info.class" );
+ }
+
/**
* Converts old TestNG configuration parameters over to new properties based configuration
* method. (if any are defined the old way)
@@ -1511,7 +1538,7 @@ public abstract class AbstractSurefireMojo
static boolean isForkModeNever( String forkMode )
{
- return ForkConfiguration.FORK_NEVER.equals( forkMode );
+ return FORK_NEVER.equals( forkMode );
}
protected boolean isForking()
@@ -1525,17 +1552,17 @@ public abstract class AbstractSurefireMojo
if ( toolchain != null && isForkModeNever( forkMode1 ) )
{
- return ForkConfiguration.FORK_ONCE;
+ return FORK_ONCE;
}
- return ForkConfiguration.getEffectiveForkMode( forkMode1 );
+ return getEffectiveForkMode( forkMode1 );
}
private List<RunOrder> getRunOrders()
{
String runOrderString = getRunOrder();
RunOrder[] runOrder = runOrderString == null ? RunOrder.DEFAULT : RunOrder.valueOfMulti( runOrderString );
- return Arrays.asList( runOrder );
+ return asList( runOrder );
}
private boolean requiresRunHistory()
@@ -1649,8 +1676,9 @@ public abstract class AbstractSurefireMojo
return new File( getBasedir(), ".surefire-" + configurationHash );
}
- StartupConfiguration createStartupConfiguration( ProviderInfo provider,
- ClassLoaderConfiguration classLoaderConfiguration )
+ private StartupConfiguration createStartupConfiguration( ProviderInfo provider, boolean isInprocess,
+ ClassLoaderConfiguration classLoaderConfiguration,
+ DefaultScanResult scanResult )
throws MojoExecutionException, MojoFailureException
{
try
@@ -1669,35 +1697,91 @@ public abstract class AbstractSurefireMojo
providerClasspath.addClassPathElementUrl( surefireArtifact.getFile().getAbsolutePath() )
.addClassPathElementUrl( getApiArtifact().getFile().getAbsolutePath() );
- final Classpath testClasspath = generateTestClasspath();
-
- getConsoleLogger().debug( testClasspath.getLogMessage( "test" ) );
- getConsoleLogger().debug( providerClasspath.getLogMessage( "provider" ) );
+ File moduleDescriptor = getModuleDescriptor();
- getConsoleLogger().debug( testClasspath.getCompactLogMessage( "test(compact)" ) );
- getConsoleLogger().debug( providerClasspath.getCompactLogMessage( "provider(compact)" ) );
-
- final ClasspathConfiguration classpathConfiguration =
- new ClasspathConfiguration( testClasspath, providerClasspath, inprocClassPath,
- effectiveIsEnableAssertions(), isChildDelegation() );
-
- return new StartupConfiguration( providerName, classpathConfiguration, classLoaderConfiguration,
- isForking(), false );
+ if ( moduleDescriptor.exists() && !isInprocess )
+ {
+ return newStartupConfigForModularClasspath( classLoaderConfiguration, providerClasspath, providerName,
+ moduleDescriptor, scanResult );
+ }
+ else
+ {
+ return newStartupConfigForNonModularClasspath( classLoaderConfiguration, providerClasspath,
+ inprocClassPath, providerName );
+ }
}
- catch ( ArtifactResolutionException e )
+ catch ( AbstractArtifactResolutionException e )
{
throw new MojoExecutionException( "Unable to generate classpath: " + e, e );
}
- catch ( ArtifactNotFoundException e )
+ catch ( InvalidVersionSpecificationException e )
{
throw new MojoExecutionException( "Unable to generate classpath: " + e, e );
}
- catch ( InvalidVersionSpecificationException e )
+ catch ( IOException e )
{
- throw new MojoExecutionException( "Unable to generate classpath: " + e, e );
+ throw new MojoExecutionException( e.getMessage(), e );
}
}
+ private StartupConfiguration newStartupConfigForNonModularClasspath(
+ ClassLoaderConfiguration classLoaderConfiguration, Classpath providerClasspath, Classpath inprocClasspath,
+ String providerName )
+ throws MojoExecutionException, MojoFailureException, InvalidVersionSpecificationException,
+ AbstractArtifactResolutionException
+ {
+ Classpath testClasspath = generateTestClasspath();
+
+ getConsoleLogger().debug( testClasspath.getLogMessage( "test classpath:" ) );
+ getConsoleLogger().debug( providerClasspath.getLogMessage( "provider classpath:" ) );
+ getConsoleLogger().debug( testClasspath.getCompactLogMessage( "test(compact) classpath:" ) );
+ getConsoleLogger().debug( providerClasspath.getCompactLogMessage( "provider(compact) classpath:" ) );
+
+ ClasspathConfiguration classpathConfiguration = new ClasspathConfiguration( testClasspath, providerClasspath,
+ inprocClasspath, effectiveIsEnableAssertions(), isChildDelegation() );
+
+ return new StartupConfiguration( providerName, classpathConfiguration, classLoaderConfiguration, isForking(),
+ false );
+ }
+
+ private StartupConfiguration newStartupConfigForModularClasspath( ClassLoaderConfiguration classLoaderConfiguration,
+ Classpath providerClasspath, String providerName,
+ File moduleDescriptor, DefaultScanResult scanResult )
+ throws MojoExecutionException, MojoFailureException, InvalidVersionSpecificationException,
+ AbstractArtifactResolutionException, IOException
+ {
+ ResolvePathsRequest<String> req = ResolvePathsRequest.withStrings( generateTestClasspath().getClassPath() )
+ .setMainModuleDescriptor( moduleDescriptor.getAbsolutePath() );
+
+ ResolvePathsResult<String> result = locationManager.resolvePaths( req );
+
+ Classpath testClasspath = new Classpath( result.getClasspathElements() );
+ Classpath testModulepath = new Classpath( result.getModulepathElements().keySet() );
+
+ SortedSet<String> packages = new TreeSet<String>();
+
+ for ( String className : scanResult.getClasses() )
+ {
+ packages.add( substringBeforeLast( className, "." ) );
+ }
+
+ ModularClasspath modularClasspath = new ModularClasspath( moduleDescriptor, testModulepath.getClassPath(),
+ packages, getTestClassesDirectory() );
+
+ ModularClasspathConfiguration classpathConfiguration = new ModularClasspathConfiguration( modularClasspath,
+ testClasspath, providerClasspath, effectiveIsEnableAssertions(), isChildDelegation() );
+
+ getConsoleLogger().debug( testClasspath.getLogMessage( "test classpath:" ) );
+ getConsoleLogger().debug( testModulepath.getLogMessage( "test modulepath:" ) );
+ getConsoleLogger().debug( providerClasspath.getLogMessage( "provider classpath:" ) );
+ getConsoleLogger().debug( testClasspath.getCompactLogMessage( "test(compact) classpath:" ) );
+ getConsoleLogger().debug( testModulepath.getCompactLogMessage( "test(compact) modulepath:" ) );
+ getConsoleLogger().debug( providerClasspath.getCompactLogMessage( "provider(compact) classpath:" ) );
+
+ return new StartupConfiguration( providerName, classpathConfiguration, classLoaderConfiguration, isForking(),
+ false );
+ }
+
private Artifact getCommonArtifact()
{
return getPluginArtifactMap().get( "org.apache.maven.surefire:maven-surefire-common" );
@@ -1800,7 +1884,7 @@ public abstract class AbstractSurefireMojo
if ( isSpecificTestSpecified() )
{
includes = new ArrayList<String>();
- Collections.addAll( includes, split( getTest(), "," ) );
+ addAll( includes, split( getTest(), "," ) );
}
else
{
@@ -1822,7 +1906,7 @@ public abstract class AbstractSurefireMojo
if ( includes == null || includes.isEmpty() )
{
- includes = Arrays.asList( getDefaultIncludes() );
+ includes = asList( getDefaultIncludes() );
}
}
@@ -1941,11 +2025,13 @@ public abstract class AbstractSurefireMojo
}
private ForkStarter createForkStarter( ProviderInfo provider, ForkConfiguration forkConfiguration,
- ClassLoaderConfiguration classLoaderConfiguration,
- RunOrderParameters runOrderParameters, ConsoleLogger log )
+ ClassLoaderConfiguration classLoaderConfiguration,
+ RunOrderParameters runOrderParameters, ConsoleLogger log,
+ DefaultScanResult scanResult )
throws MojoExecutionException, MojoFailureException
{
- StartupConfiguration startupConfiguration = createStartupConfiguration( provider, classLoaderConfiguration );
+ StartupConfiguration startupConfiguration =
+ createStartupConfiguration( provider, false, classLoaderConfiguration, scanResult );
String configChecksum = getConfigChecksum();
StartupReportConfiguration startupReportConfiguration = getStartupReportConfiguration( configChecksum );
ProviderConfiguration providerConfiguration = createProviderConfiguration( runOrderParameters );
@@ -1954,16 +2040,18 @@ public abstract class AbstractSurefireMojo
}
private InPluginVMSurefireStarter createInprocessStarter( ProviderInfo provider,
- ClassLoaderConfiguration classLoaderConfiguration,
- RunOrderParameters runOrderParameters )
+ ClassLoaderConfiguration classLoaderConfiguration,
+ RunOrderParameters runOrderParameters,
+ DefaultScanResult scanResult )
throws MojoExecutionException, MojoFailureException
{
- StartupConfiguration startupConfiguration = createStartupConfiguration( provider, classLoaderConfiguration );
+ StartupConfiguration startupConfiguration =
+ createStartupConfiguration( provider, true, classLoaderConfiguration, scanResult );
String configChecksum = getConfigChecksum();
StartupReportConfiguration startupReportConfiguration = getStartupReportConfiguration( configChecksum );
ProviderConfiguration providerConfiguration = createProviderConfiguration( runOrderParameters );
- return new InPluginVMSurefireStarter( startupConfiguration, providerConfiguration,
- startupReportConfiguration, consoleLogger );
+ return new InPluginVMSurefireStarter( startupConfiguration, providerConfiguration, startupReportConfiguration,
+ getConsoleLogger() );
}
private ForkConfiguration getForkConfiguration() throws MojoFailureException
@@ -1973,36 +2061,76 @@ public abstract class AbstractSurefireMojo
Artifact shadeFire = getPluginArtifactMap().get( "org.apache.maven.surefire:surefire-shadefire" );
// todo: 150 milli seconds, try to fetch List<String> within classpath asynchronously
- final Classpath bootClasspathConfiguration =
- getArtifactClasspath( shadeFire != null ? shadeFire : surefireBooterArtifact );
-
- return new ForkConfiguration( bootClasspathConfiguration, tmpDir, getEffectiveDebugForkedProcess(),
- getEffectiveJvm(),
- getWorkingDirectory() != null ? getWorkingDirectory() : getBasedir(),
- getProject().getModel().getProperties(),
- getArgLine(), getEnvironmentVariables(), getConsoleLogger().isDebugEnabled(),
- getEffectiveForkCount(), reuseForks, PLATFORM );
+ Classpath bootClasspath = getArtifactClasspath( shadeFire != null ? shadeFire : surefireBooterArtifact );
+
+ Platform platform = PLATFORM.withJdkExecAttributesForTests( getEffectiveJvm() );
+
+ if ( platform.getJdkExecAttributesForTests().isJava9AtLeast() && existsModuleDescriptor() )
+ {
+ return new ModularClasspathForkConfiguration( bootClasspath,
+ tmpDir,
+ getEffectiveDebugForkedProcess(),
+ getWorkingDirectory() != null ? getWorkingDirectory() : getBasedir(),
+ getProject().getModel().getProperties(),
+ getArgLine(),
+ getEnvironmentVariables(),
+ getConsoleLogger().isDebugEnabled(),
+ getEffectiveForkCount(),
+ reuseForks,
+ platform,
+ getConsoleLogger() );
+ }
+ else if ( getClassLoaderConfiguration().isManifestOnlyJarRequestedAndUsable() )
+ {
+ return new JarManifestForkConfiguration( bootClasspath,
+ tmpDir,
+ getEffectiveDebugForkedProcess(),
+ getWorkingDirectory() != null ? getWorkingDirectory() : getBasedir(),
+ getProject().getModel().getProperties(),
+ getArgLine(),
+ getEnvironmentVariables(),
+ getConsoleLogger().isDebugEnabled(),
+ getEffectiveForkCount(),
+ reuseForks,
+ platform,
+ getConsoleLogger() );
+ }
+ else
+ {
+ return new ClasspathForkConfiguration( bootClasspath,
+ tmpDir,
+ getEffectiveDebugForkedProcess(),
+ getWorkingDirectory() != null ? getWorkingDirectory() : getBasedir(),
+ getProject().getModel().getProperties(),
+ getArgLine(),
+ getEnvironmentVariables(),
+ getConsoleLogger().isDebugEnabled(),
+ getEffectiveForkCount(),
+ reuseForks,
+ platform,
+ getConsoleLogger() );
+ }
}
private void convertDeprecatedForkMode()
{
String effectiveForkMode = getEffectiveForkMode();
// FORK_ONCE (default) is represented by the default values of forkCount and reuseForks
- if ( ForkConfiguration.FORK_PERTHREAD.equals( effectiveForkMode ) )
+ if ( FORK_PERTHREAD.equals( effectiveForkMode ) )
{
forkCount = String.valueOf( threadCount );
}
- else if ( ForkConfiguration.FORK_NEVER.equals( effectiveForkMode ) )
+ else if ( FORK_NEVER.equals( effectiveForkMode ) )
{
forkCount = "0";
}
- else if ( ForkConfiguration.FORK_ALWAYS.equals( effectiveForkMode ) )
+ else if ( FORK_ALWAYS.equals( effectiveForkMode ) )
{
forkCount = "1";
reuseForks = false;
}
- if ( !ForkConfiguration.FORK_ONCE.equals( getForkMode() ) )
+ if ( !FORK_ONCE.equals( getForkMode() ) )
{
getConsoleLogger().warning( "The parameter forkMode is deprecated since version 2.14. "
+ "Use forkCount and reuseForks instead." );
@@ -2263,14 +2391,14 @@ public abstract class AbstractSurefireMojo
if ( getClasspathDependencyScopeExclude() != null && !getClasspathDependencyScopeExclude().isEmpty() )
{
ArtifactFilter dependencyFilter = new ScopeArtifactFilter( getClasspathDependencyScopeExclude() );
- classpathArtifacts = this.filterArtifacts( classpathArtifacts, dependencyFilter );
+ classpathArtifacts = filterArtifacts( classpathArtifacts, dependencyFilter );
}
if ( getClasspathDependencyExcludes() != null )
{
- ArtifactFilter dependencyFilter =
- new PatternIncludesArtifactFilter( Arrays.asList( getClasspathDependencyExcludes() ) );
- classpathArtifacts = this.filterArtifacts( classpathArtifacts, dependencyFilter );
+ List<String> excludedDependencies = asList( getClasspathDependencyExcludes() );
+ ArtifactFilter dependencyFilter = new PatternIncludesArtifactFilter( excludedDependencies );
+ classpathArtifacts = filterArtifacts( classpathArtifacts, dependencyFilter );
}
for ( Artifact artifact : classpathArtifacts )
@@ -2292,7 +2420,7 @@ public abstract class AbstractSurefireMojo
{
if ( classpathElement != null )
{
- Collections.addAll( classpath, split( classpathElement, "," ) );
+ addAll( classpath, split( classpathElement, "," ) );
}
}
}
@@ -2337,7 +2465,7 @@ public abstract class AbstractSurefireMojo
* @param filter The filter to apply
* @return The filtered result
*/
- private Set<Artifact> filterArtifacts( Set<Artifact> artifacts, ArtifactFilter filter )
+ private static Set<Artifact> filterArtifacts( Set<Artifact> artifacts, ArtifactFilter filter )
{
Set<Artifact> filteredArtifacts = new LinkedHashSet<Artifact>();
@@ -2486,7 +2614,7 @@ public abstract class AbstractSurefireMojo
private void ensureThreadCountWithPerThread()
throws MojoFailureException
{
- if ( ForkConfiguration.FORK_PERTHREAD.equals( getEffectiveForkMode() ) && getThreadCount() < 1 )
+ if ( FORK_PERTHREAD.equals( getEffectiveForkMode() ) && getThreadCount() < 1 )
{
throw new MojoFailureException( "Fork mode perthread requires a thread count" );
}
@@ -3355,7 +3483,7 @@ public abstract class AbstractSurefireMojo
{
if ( getArgLine() != null )
{
- List<String> args = Arrays.asList( getArgLine().split( " " ) );
+ List<String> args = asList( getArgLine().split( " " ) );
if ( args.contains( "-da" ) || args.contains( "-disableassertions" ) )
{
return false;
@@ -3510,4 +3638,25 @@ public abstract class AbstractSurefireMojo
{
this.tempDir = tempDir;
}
+
+ private static String getEffectiveForkMode( String forkMode )
+ {
+ if ( "pertest".equalsIgnoreCase( forkMode ) )
+ {
+ return FORK_ALWAYS;
+ }
+ else if ( "none".equalsIgnoreCase( forkMode ) )
+ {
+ return FORK_NEVER;
+ }
+ else if ( forkMode.equals( FORK_NEVER ) || forkMode.equals( FORK_ONCE )
+ || forkMode.equals( FORK_ALWAYS ) || forkMode.equals( FORK_PERTHREAD ) )
+ {
+ return forkMode;
+ }
+ else
+ {
+ throw new IllegalArgumentException( "Fork mode " + forkMode + " is not a legal value" );
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/f337881f/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/InPluginVMSurefireStarter.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/InPluginVMSurefireStarter.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/InPluginVMSurefireStarter.java
index b97c192..1d85001 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/InPluginVMSurefireStarter.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/InPluginVMSurefireStarter.java
@@ -20,6 +20,7 @@ package org.apache.maven.plugin.surefire;
*/
import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
+import org.apache.maven.surefire.booter.ClasspathConfiguration;
import org.apache.maven.surefire.booter.ProviderConfiguration;
import org.apache.maven.surefire.booter.StartupConfiguration;
import org.apache.maven.surefire.booter.SurefireExecutionException;
@@ -73,7 +74,9 @@ public class InPluginVMSurefireStarter
scanResult.writeTo( providerProperties );
startupConfig.writeSurefireTestClasspathProperty();
- ClassLoader testClassLoader = startupConfig.getClasspathConfiguration().createMergedClassLoader();
+ ClassLoader testClassLoader = startupConfig.getClasspathConfiguration()
+ .toRealPath( ClasspathConfiguration.class )
+ .createMergedClassLoader();
CommonReflector surefireReflector = new CommonReflector( testClassLoader );
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/f337881f/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/AbstractClasspathForkConfiguration.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/AbstractClasspathForkConfiguration.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/AbstractClasspathForkConfiguration.java
new file mode 100644
index 0000000..90d1a1d
--- /dev/null
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/AbstractClasspathForkConfiguration.java
@@ -0,0 +1,73 @@
+package org.apache.maven.plugin.surefire.booterclient;
+
+/*
+ * 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.plugin.surefire.log.api.ConsoleLogger;
+import org.apache.maven.surefire.booter.Classpath;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import java.io.File;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.21.0.Jigsaw
+ */
+abstract class AbstractClasspathForkConfiguration
+ extends DefaultForkConfiguration
+{
+ private static final String ADD_MODULES = "--add-modules";
+ private static final String ADD_MODULES_VALUE = "java.se.ee";
+ private static final String ALL_JAVA_API = ADD_MODULES + " " + ADD_MODULES_VALUE;
+
+ @SuppressWarnings( "checkstyle:parameternumber" )
+ public AbstractClasspathForkConfiguration( @Nonnull Classpath bootClasspath,
+ @Nonnull File tempDirectory,
+ @Nullable String debugLine,
+ @Nonnull File workingDirectory,
+ @Nonnull Properties modelProperties,
+ @Nullable String argLine,
+ @Nonnull Map<String, String> environmentVariables,
+ boolean debug,
+ int forkCount,
+ boolean reuseForks,
+ @Nonnull Platform pluginPlatform,
+ @Nonnull ConsoleLogger log )
+ {
+ super( bootClasspath, tempDirectory, debugLine, workingDirectory, modelProperties, argLine,
+ environmentVariables, debug, forkCount, reuseForks, pluginPlatform, log );
+ }
+
+ @Override
+ @Nonnull
+ protected String extendJvmArgLine( @Nonnull String jvmArgLine )
+ {
+ if ( getJdkForTests().isJava9AtLeast() && !jvmArgLine.contains( ADD_MODULES ) )
+ {
+ return jvmArgLine.isEmpty() ? ALL_JAVA_API : ALL_JAVA_API + " " + jvmArgLine;
+ }
+ else
+ {
+ return jvmArgLine;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/f337881f/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java
index 591e89c..97140ef 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java
@@ -19,17 +19,12 @@ package org.apache.maven.plugin.surefire.booterclient;
* under the License.
*/
-import java.io.File;
-import java.io.IOException;
-import java.util.List;
-
import org.apache.maven.plugin.surefire.SurefireProperties;
+import org.apache.maven.surefire.booter.AbstractPathConfiguration;
import org.apache.maven.surefire.booter.ClassLoaderConfiguration;
-import org.apache.maven.surefire.booter.ClasspathConfiguration;
import org.apache.maven.surefire.booter.KeyValueSource;
import org.apache.maven.surefire.booter.ProviderConfiguration;
import org.apache.maven.surefire.booter.StartupConfiguration;
-import org.apache.maven.surefire.booter.SystemPropertyManager;
import org.apache.maven.surefire.cli.CommandLineOption;
import org.apache.maven.surefire.report.ReporterConfiguration;
import org.apache.maven.surefire.testset.DirectoryScannerParameters;
@@ -39,8 +34,40 @@ import org.apache.maven.surefire.testset.TestListResolver;
import org.apache.maven.surefire.testset.TestRequest;
import org.apache.maven.surefire.util.RunOrder;
-// CHECKSTYLE_OFF: imports
-import static org.apache.maven.surefire.booter.BooterConstants.*;
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+import static org.apache.maven.surefire.booter.AbstractPathConfiguration.CHILD_DELEGATION;
+import static org.apache.maven.surefire.booter.AbstractPathConfiguration.CLASSPATH;
+import static org.apache.maven.surefire.booter.AbstractPathConfiguration.ENABLE_ASSERTIONS;
+import static org.apache.maven.surefire.booter.AbstractPathConfiguration.SUREFIRE_CLASSPATH;
+import static org.apache.maven.surefire.booter.BooterConstants.EXCLUDES_PROPERTY_PREFIX;
+import static org.apache.maven.surefire.booter.BooterConstants.FAIL_FAST_COUNT;
+import static org.apache.maven.surefire.booter.BooterConstants.FAILIFNOTESTS;
+import static org.apache.maven.surefire.booter.BooterConstants.FORKTESTSET;
+import static org.apache.maven.surefire.booter.BooterConstants.FORKTESTSET_PREFER_TESTS_FROM_IN_STREAM;
+import static org.apache.maven.surefire.booter.BooterConstants.INCLUDES_PROPERTY_PREFIX;
+import static org.apache.maven.surefire.booter.BooterConstants.ISTRIMSTACKTRACE;
+import static org.apache.maven.surefire.booter.BooterConstants.MAIN_CLI_OPTIONS;
+import static org.apache.maven.surefire.booter.BooterConstants.PLUGIN_PID;
+import static org.apache.maven.surefire.booter.BooterConstants.PROVIDER_CONFIGURATION;
+import static org.apache.maven.surefire.booter.BooterConstants.REPORTSDIRECTORY;
+import static org.apache.maven.surefire.booter.BooterConstants.REQUESTEDTEST;
+import static org.apache.maven.surefire.booter.BooterConstants.RERUN_FAILING_TESTS_COUNT;
+import static org.apache.maven.surefire.booter.BooterConstants.RUN_ORDER;
+import static org.apache.maven.surefire.booter.BooterConstants.RUN_STATISTICS_FILE;
+import static org.apache.maven.surefire.booter.BooterConstants.SHUTDOWN;
+import static org.apache.maven.surefire.booter.BooterConstants.SOURCE_DIRECTORY;
+import static org.apache.maven.surefire.booter.BooterConstants.SPECIFIC_TEST_PROPERTY_PREFIX;
+import static org.apache.maven.surefire.booter.BooterConstants.SYSTEM_EXIT_TIMEOUT;
+import static org.apache.maven.surefire.booter.BooterConstants.TEST_CLASSES_DIRECTORY;
+import static org.apache.maven.surefire.booter.BooterConstants.TEST_SUITE_XML_FILES;
+import static org.apache.maven.surefire.booter.BooterConstants.TESTARTIFACT_CLASSIFIER;
+import static org.apache.maven.surefire.booter.BooterConstants.TESTARTIFACT_VERSION;
+import static org.apache.maven.surefire.booter.BooterConstants.USEMANIFESTONLYJAR;
+import static org.apache.maven.surefire.booter.BooterConstants.USESYSTEMCLASSLOADER;
+import static org.apache.maven.surefire.booter.SystemPropertyManager.writePropertiesFile;
/**
* Knows how to serialize and deserialize the booter configuration.
@@ -78,11 +105,11 @@ class BooterSerializer
properties.setProperty( PLUGIN_PID, pid );
- ClasspathConfiguration cp = providerConfiguration.getClasspathConfiguration();
- properties.setClasspath( ClasspathConfiguration.CLASSPATH, cp.getTestClasspath() );
- properties.setClasspath( ClasspathConfiguration.SUREFIRE_CLASSPATH, cp.getProviderClasspath() );
- properties.setProperty( ClasspathConfiguration.ENABLE_ASSERTIONS, String.valueOf( cp.isEnableAssertions() ) );
- properties.setProperty( ClasspathConfiguration.CHILD_DELEGATION, String.valueOf( cp.isChildDelegation() ) );
+ AbstractPathConfiguration cp = providerConfiguration.getClasspathConfiguration();
+ properties.setClasspath( CLASSPATH, cp.getTestClasspath() );
+ properties.setClasspath( SUREFIRE_CLASSPATH, cp.getProviderClasspath() );
+ properties.setProperty( ENABLE_ASSERTIONS, toString( cp.isEnableAssertions() ) );
+ properties.setProperty( CHILD_DELEGATION, toString( cp.isChildDelegation() ) );
TestArtifactInfo testNg = booterConfiguration.getTestArtifact();
if ( testNg != null )
@@ -101,18 +128,17 @@ class BooterSerializer
properties.addList( testSuiteDefinition.getSuiteXmlFiles(), TEST_SUITE_XML_FILES );
TestListResolver testFilter = testSuiteDefinition.getTestListResolver();
properties.setProperty( REQUESTEDTEST, testFilter == null ? "" : testFilter.getPluginParameterTest() );
- properties.setNullableProperty( RERUN_FAILING_TESTS_COUNT,
- String.valueOf( testSuiteDefinition.getRerunFailingTestsCount() ) );
+ int rerunFailingTestsCount = testSuiteDefinition.getRerunFailingTestsCount();
+ properties.setNullableProperty( RERUN_FAILING_TESTS_COUNT, toString( rerunFailingTestsCount ) );
}
DirectoryScannerParameters directoryScannerParameters = booterConfiguration.getDirScannerParams();
if ( directoryScannerParameters != null )
{
- properties.setProperty( FAILIFNOTESTS, String.valueOf( directoryScannerParameters.isFailIfNoTests() ) );
+ properties.setProperty( FAILIFNOTESTS, toString( directoryScannerParameters.isFailIfNoTests() ) );
properties.addList( directoryScannerParameters.getIncludes(), INCLUDES_PROPERTY_PREFIX );
properties.addList( directoryScannerParameters.getExcludes(), EXCLUDES_PROPERTY_PREFIX );
properties.addList( directoryScannerParameters.getSpecificTests(), SPECIFIC_TEST_PROPERTY_PREFIX );
-
properties.setProperty( TEST_CLASSES_DIRECTORY, directoryScannerParameters.getTestClassesDirectory() );
}
@@ -124,46 +150,40 @@ class BooterSerializer
}
ReporterConfiguration reporterConfiguration = booterConfiguration.getReporterConfiguration();
-
boolean rep = reporterConfiguration.isTrimStackTrace();
properties.setProperty( ISTRIMSTACKTRACE, rep );
properties.setProperty( REPORTSDIRECTORY, reporterConfiguration.getReportsDirectory() );
ClassLoaderConfiguration classLoaderConfig = providerConfiguration.getClassLoaderConfiguration();
- properties.setProperty( USESYSTEMCLASSLOADER, String.valueOf( classLoaderConfig.isUseSystemClassLoader() ) );
- properties.setProperty( USEMANIFESTONLYJAR, String.valueOf( classLoaderConfig.isUseManifestOnlyJar() ) );
- properties.setProperty( FAILIFNOTESTS, String.valueOf( booterConfiguration.isFailIfNoTests() ) );
+ properties.setProperty( USESYSTEMCLASSLOADER, toString( classLoaderConfig.isUseSystemClassLoader() ) );
+ properties.setProperty( USEMANIFESTONLYJAR, toString( classLoaderConfig.isUseManifestOnlyJar() ) );
+ properties.setProperty( FAILIFNOTESTS, toString( booterConfiguration.isFailIfNoTests() ) );
properties.setProperty( PROVIDER_CONFIGURATION, providerConfiguration.getProviderClassName() );
- properties.setProperty( FAIL_FAST_COUNT, String.valueOf( booterConfiguration.getSkipAfterFailureCount() ) );
+ properties.setProperty( FAIL_FAST_COUNT, toString( booterConfiguration.getSkipAfterFailureCount() ) );
properties.setProperty( SHUTDOWN, booterConfiguration.getShutdown().name() );
List<CommandLineOption> mainCliOptions = booterConfiguration.getMainCliOptions();
if ( mainCliOptions != null )
{
properties.addList( mainCliOptions, MAIN_CLI_OPTIONS );
}
+ properties.setNullableProperty( SYSTEM_EXIT_TIMEOUT, toString( booterConfiguration.getSystemExitTimeout() ) );
- properties.setNullableProperty( SYSTEM_EXIT_TIMEOUT,
- String.valueOf( booterConfiguration.getSystemExitTimeout() ) );
-
- return SystemPropertyManager.writePropertiesFile( properties, forkConfiguration.getTempDirectory(),
- "surefire", forkConfiguration.isDebug() );
+ File surefireTmpDir = forkConfiguration.getTempDirectory();
+ boolean debug = forkConfiguration.isDebug();
+ return writePropertiesFile( properties, surefireTmpDir, "surefire", debug );
}
- private String getTypeEncoded( Object value )
+ private static String getTypeEncoded( Object value )
{
if ( value == null )
{
return null;
}
- String valueToUse;
- if ( value instanceof Class )
- {
- valueToUse = ( (Class<?>) value ).getName();
- }
- else
- {
- valueToUse = value.toString();
- }
+ String valueToUse = value instanceof Class ? ( (Class<?>) value ).getName() : value.toString();
return value.getClass().getName() + "|" + valueToUse;
}
+ private static String toString( Object o )
+ {
+ return String.valueOf( o );
+ }
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/f337881f/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ClasspathForkConfiguration.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ClasspathForkConfiguration.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ClasspathForkConfiguration.java
new file mode 100644
index 0000000..28b966e
--- /dev/null
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ClasspathForkConfiguration.java
@@ -0,0 +1,59 @@
+package org.apache.maven.plugin.surefire.booterclient;
+
+/*
+ * 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.plugin.surefire.booterclient.lazytestprovider.OutputStreamFlushableCommandline;
+import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
+import org.apache.maven.surefire.booter.Classpath;
+import org.apache.maven.surefire.booter.StartupConfiguration;
+import org.apache.maven.surefire.booter.SurefireBooterForkException;
+
+import java.io.File;
+import java.util.Map;
+import java.util.Properties;
+
+import static org.apache.maven.shared.utils.StringUtils.join;
+
+/**
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.21.0.Jigsaw
+ */
+public final class ClasspathForkConfiguration
+ extends AbstractClasspathForkConfiguration
+{
+ @SuppressWarnings( "checkstyle:parameternumber" )
+ public ClasspathForkConfiguration( Classpath bootClasspath, File tempDirectory, String debugLine,
+ File workingDirectory, Properties modelProperties, String argLine,
+ Map<String, String> environmentVariables, boolean debug, int forkCount,
+ boolean reuseForks, Platform pluginPlatform, ConsoleLogger log )
+ {
+ super( bootClasspath, tempDirectory, debugLine, workingDirectory, modelProperties, argLine,
+ environmentVariables, debug, forkCount, reuseForks, pluginPlatform, log );
+ }
+
+ @Override
+ protected void resolveClasspath( OutputStreamFlushableCommandline cli, String booterThatHasMainMethod,
+ StartupConfiguration config )
+ throws SurefireBooterForkException
+ {
+ cli.addEnvironment( "CLASSPATH", join( toCompleteClasspath( config ).iterator(), File.pathSeparator ) );
+ cli.createArg().setValue( booterThatHasMainMethod );
+ }
+}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/f337881f/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/DefaultForkConfiguration.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/DefaultForkConfiguration.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/DefaultForkConfiguration.java
new file mode 100644
index 0000000..8c3a9e6
--- /dev/null
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/DefaultForkConfiguration.java
@@ -0,0 +1,343 @@
+package org.apache.maven.plugin.surefire.booterclient;
+
+/*
+ * 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.plugin.surefire.JdkAttributes;
+import org.apache.maven.plugin.surefire.booterclient.lazytestprovider.OutputStreamFlushableCommandline;
+import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
+import org.apache.maven.surefire.booter.AbstractPathConfiguration;
+import org.apache.maven.surefire.booter.Classpath;
+import org.apache.maven.surefire.booter.StartupConfiguration;
+import org.apache.maven.surefire.booter.SurefireBooterForkException;
+import org.apache.maven.surefire.util.internal.ImmutableMap;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import java.io.File;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Properties;
+
+import static org.apache.maven.plugin.surefire.AbstractSurefireMojo.FORK_NUMBER_PLACEHOLDER;
+import static org.apache.maven.plugin.surefire.AbstractSurefireMojo.THREAD_NUMBER_PLACEHOLDER;
+import static org.apache.maven.plugin.surefire.util.Relocator.relocate;
+import static org.apache.maven.surefire.booter.Classpath.join;
+
+/**
+ * Basic framework which constructs CLI.
+ *
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.21.0.Jigsaw
+ */
+public abstract class DefaultForkConfiguration
+ extends ForkConfiguration
+{
+ @Nonnull private final Classpath booterClasspath;
+ @Nonnull private final File tempDirectory;
+ @Nullable
+ private final String debugLine;
+ @Nonnull private final File workingDirectory;
+ @Nonnull private final Properties modelProperties;
+ @Nullable private final String argLine;
+ @Nonnull private final Map<String, String> environmentVariables;
+ private final boolean debug;
+ private final int forkCount;
+ private final boolean reuseForks;
+ @Nonnull private final Platform pluginPlatform;
+ @Nonnull private final ConsoleLogger log;
+
+ @SuppressWarnings( "checkstyle:parameternumber" )
+ protected DefaultForkConfiguration( @Nonnull Classpath booterClasspath,
+ @Nonnull File tempDirectory,
+ @Nullable String debugLine,
+ @Nonnull File workingDirectory,
+ @Nonnull Properties modelProperties,
+ @Nullable String argLine,
+ @Nonnull Map<String, String> environmentVariables,
+ boolean debug,
+ int forkCount,
+ boolean reuseForks,
+ @Nonnull Platform pluginPlatform,
+ @Nonnull ConsoleLogger log )
+ {
+ this.booterClasspath = booterClasspath;
+ this.tempDirectory = tempDirectory;
+ this.debugLine = debugLine;
+ this.workingDirectory = workingDirectory;
+ this.modelProperties = modelProperties;
+ this.argLine = argLine;
+ this.environmentVariables = toImmutable( environmentVariables );
+ this.debug = debug;
+ this.forkCount = forkCount;
+ this.reuseForks = reuseForks;
+ this.pluginPlatform = pluginPlatform;
+ this.log = log;
+ }
+
+ protected abstract void resolveClasspath( OutputStreamFlushableCommandline cli, String booterThatHasMainMethod,
+ StartupConfiguration config )
+ throws SurefireBooterForkException;
+
+ @Nonnull
+ protected String extendJvmArgLine( @Nonnull String jvmArgLine )
+ {
+ return jvmArgLine;
+ }
+
+ /**
+ * @param config The startup configuration
+ * @param forkNumber index of forked JVM, to be the replacement in the argLine
+ * @return CommandLine able to flush entire command going to be sent to forked JVM
+ * @throws org.apache.maven.surefire.booter.SurefireBooterForkException when unable to perform the fork
+ */
+ @Nonnull
+ @Override
+ public OutputStreamFlushableCommandline createCommandLine( @Nonnull StartupConfiguration config, int forkNumber )
+ throws SurefireBooterForkException
+ {
+ OutputStreamFlushableCommandline cli = new OutputStreamFlushableCommandline();
+
+ cli.setWorkingDirectory( getWorkingDirectory( forkNumber ).getAbsolutePath() );
+
+ for ( Entry<String, String> entry : getEnvironmentVariables().entrySet() )
+ {
+ String value = entry.getValue();
+ cli.addEnvironment( entry.getKey(), value == null ? "" : value );
+ }
+
+ cli.setExecutable( getJdkForTests().getJvmExecutable() );
+
+ String jvmArgLine = newJvmArgLine( forkNumber );
+ if ( !jvmArgLine.isEmpty() )
+ {
+ cli.createArg()
+ .setLine( jvmArgLine );
+ }
+
+ if ( getDebugLine() != null && !getDebugLine().isEmpty() )
+ {
+ cli.createArg()
+ .setLine( getDebugLine() );
+ }
+
+ resolveClasspath( cli, findStartClass( config ), config );
+
+ return cli;
+ }
+
+ protected List<String> toCompleteClasspath( StartupConfiguration conf ) throws SurefireBooterForkException
+ {
+ AbstractPathConfiguration pathConfig = conf.getClasspathConfiguration();
+ if ( pathConfig.isClassPathConfig() == pathConfig.isModularPathConfig() )
+ {
+ throw new SurefireBooterForkException( "Could not find class-path config nor modular class-path either." );
+ }
+
+ //todo this could probably be simplified further
+ Classpath bootClasspath = conf.isProviderMainClass() ? pathConfig.getProviderClasspath() : getBooterClasspath();
+ Classpath testClasspath = pathConfig.getTestClasspath();
+ Classpath providerClasspath = pathConfig.getProviderClasspath();
+
+ Classpath completeClasspath = join( join( bootClasspath, testClasspath ), providerClasspath );
+
+ log.debug( completeClasspath.getLogMessage( "boot classpath:" ) );
+ log.debug( completeClasspath.getCompactLogMessage( "boot(compact) classpath:" ) );
+
+ return completeClasspath.getClassPath();
+ }
+
+ @Nonnull
+ private File getWorkingDirectory( int forkNumber )
+ throws SurefireBooterForkException
+ {
+ File cwd = new File( replaceThreadNumberPlaceholder( getWorkingDirectory().getAbsolutePath(), forkNumber ) );
+
+ if ( !cwd.exists() && !cwd.mkdirs() )
+ {
+ throw new SurefireBooterForkException( "Cannot create workingDirectory " + cwd.getAbsolutePath() );
+ }
+
+ if ( !cwd.isDirectory() )
+ {
+ throw new SurefireBooterForkException(
+ "WorkingDirectory " + cwd.getAbsolutePath() + " exists and is not a directory" );
+ }
+ return cwd;
+ }
+
+ @Nonnull
+ private static String replaceThreadNumberPlaceholder( @Nonnull String argLine, int threadNumber )
+ {
+ String threadNumberAsString = String.valueOf( threadNumber );
+ return argLine.replace( THREAD_NUMBER_PLACEHOLDER, threadNumberAsString )
+ .replace( FORK_NUMBER_PLACEHOLDER, threadNumberAsString );
+ }
+
+ /**
+ * Replaces expressions <pre>@{property-name}</pre> with the corresponding properties
+ * from the model. This allows late evaluation of property values when the plugin is executed (as compared
+ * to evaluation when the pom is parsed as is done with <pre>${property-name}</pre> expressions).
+ *
+ * This allows other plugins to modify or set properties with the changes getting picked up by surefire.
+ */
+ @Nonnull
+ private String interpolateArgLineWithPropertyExpressions()
+ {
+ if ( getArgLine() == null )
+ {
+ return "";
+ }
+
+ String resolvedArgLine = getArgLine().trim();
+
+ if ( resolvedArgLine.isEmpty() )
+ {
+ return "";
+ }
+
+ for ( final String key : getModelProperties().stringPropertyNames() )
+ {
+ String field = "@{" + key + "}";
+ if ( getArgLine().contains( field ) )
+ {
+ resolvedArgLine = resolvedArgLine.replace( field, getModelProperties().getProperty( key, "" ) );
+ }
+ }
+
+ return resolvedArgLine;
+ }
+
+ @Nonnull
+ private static String stripNewLines( @Nonnull String argLine )
+ {
+ return argLine.replace( "\n", " " ).replace( "\r", " " );
+ }
+
+ /**
+ * Immutable map.
+ *
+ * @param map immutable map copies elements from <code>map</code>
+ * @param <K> key type
+ * @param <V> value type
+ * @return never returns null
+ */
+ @Nonnull
+ private static <K, V> Map<K, V> toImmutable( @Nullable Map<K, V> map )
+ {
+ return map == null ? Collections.<K, V>emptyMap() : new ImmutableMap<K, V>( map );
+ }
+
+ @Override
+ @Nonnull
+ public File getTempDirectory()
+ {
+ return tempDirectory;
+ }
+
+ @Override
+ @Nullable
+ protected String getDebugLine()
+ {
+ return debugLine;
+ }
+
+ @Override
+ @Nonnull
+ protected File getWorkingDirectory()
+ {
+ return workingDirectory;
+ }
+
+ @Override
+ @Nonnull
+ protected Properties getModelProperties()
+ {
+ return modelProperties;
+ }
+
+ @Override
+ @Nullable
+ protected String getArgLine()
+ {
+ return argLine;
+ }
+
+ @Override
+ @Nonnull
+ protected Map<String, String> getEnvironmentVariables()
+ {
+ return environmentVariables;
+ }
+
+ @Override
+ protected boolean isDebug()
+ {
+ return debug;
+ }
+
+ @Override
+ protected int getForkCount()
+ {
+ return forkCount;
+ }
+
+ @Override
+ protected boolean isReuseForks()
+ {
+ return reuseForks;
+ }
+
+ @Override
+ @Nonnull
+ protected Platform getPluginPlatform()
+ {
+ return pluginPlatform;
+ }
+
+ @Override
+ @Nonnull
+ protected JdkAttributes getJdkForTests()
+ {
+ return getPluginPlatform().getJdkExecAttributesForTests();
+ }
+
+ @Override
+ @Nonnull
+ protected Classpath getBooterClasspath()
+ {
+ return booterClasspath;
+ }
+
+ @Nonnull
+ private String newJvmArgLine( int forks )
+ {
+ String interpolatedArgs = stripNewLines( interpolateArgLineWithPropertyExpressions() );
+ String argsWithReplacedForkNumbers = replaceThreadNumberPlaceholder( interpolatedArgs, forks );
+ return extendJvmArgLine( argsWithReplacedForkNumbers );
+ }
+
+ @Nonnull
+ private static String findStartClass( StartupConfiguration config )
+ {
+ return config.isShadefire() ? relocate( DEFAULT_PROVIDER_CLASS ) : DEFAULT_PROVIDER_CLASS;
+ }
+}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/f337881f/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkConfiguration.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkConfiguration.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkConfiguration.java
index c962424..1ec0fc3 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkConfiguration.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkConfiguration.java
@@ -19,371 +19,48 @@ package org.apache.maven.plugin.surefire.booterclient;
* under the License.
*/
-import org.apache.maven.plugin.surefire.AbstractSurefireMojo;
import org.apache.maven.plugin.surefire.JdkAttributes;
import org.apache.maven.plugin.surefire.booterclient.lazytestprovider.OutputStreamFlushableCommandline;
-import org.apache.maven.plugin.surefire.util.Relocator;
import org.apache.maven.surefire.booter.Classpath;
import org.apache.maven.surefire.booter.ForkedBooter;
import org.apache.maven.surefire.booter.StartupConfiguration;
import org.apache.maven.surefire.booter.SurefireBooterForkException;
-import org.apache.maven.surefire.util.internal.ImmutableMap;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
import java.util.Map;
import java.util.Properties;
-import java.util.jar.JarEntry;
-import java.util.jar.JarOutputStream;
-import java.util.jar.Manifest;
-
-import static org.apache.maven.plugin.surefire.SurefireHelper.escapeToPlatformPath;
-import static org.apache.maven.shared.utils.StringUtils.join;
/**
* Configuration for forking tests.
- *
- * @author <a href="mailto:brett@apache.org">Brett Porter</a>
- * @author <a href="mailto:kenney@apache.org">Kenney Westerhof</a>
- * @author <a href="mailto:krosenvold@apache.org">Kristian Rosenvold</a>
*/
-public class ForkConfiguration
+public abstract class ForkConfiguration
{
- public static final String FORK_ONCE = "once";
-
- public static final String FORK_ALWAYS = "always";
-
- public static final String FORK_NEVER = "never";
-
- public static final String FORK_PERTHREAD = "perthread";
-
- private final int forkCount;
-
- private final boolean reuseForks;
-
- private final Classpath bootClasspathConfiguration;
-
- private final JdkAttributes jdk;
-
- private final Properties modelProperties;
-
- private final String argLine;
-
- private final Map<String, String> environmentVariables;
-
- private final File workingDirectory;
-
- private final File tempDirectory;
-
- private final boolean debug;
-
- private final String debugLine;
-
- private final Platform pluginPlatform;
-
- @SuppressWarnings( "checkstyle:parameternumber" )
- public ForkConfiguration( Classpath bootClasspathConfiguration, File tmpDir, String debugLine,
- JdkAttributes jdk, File workingDirectory, Properties modelProperties, String argLine,
- Map<String, String> environmentVariables, boolean debugEnabled, int forkCount,
- boolean reuseForks, Platform pluginPlatform )
- {
- this.bootClasspathConfiguration = bootClasspathConfiguration;
- this.tempDirectory = tmpDir;
- this.debugLine = debugLine;
- this.jdk = jdk;
- this.workingDirectory = workingDirectory;
- this.modelProperties = modelProperties;
- this.argLine = argLine;
- this.environmentVariables = toImmutable( environmentVariables );
- this.debug = debugEnabled;
- this.forkCount = forkCount;
- this.reuseForks = reuseForks;
- this.pluginPlatform = pluginPlatform;
- }
-
- public Classpath getBootClasspath()
- {
- return bootClasspathConfiguration;
- }
-
- public static String getEffectiveForkMode( String forkMode )
- {
- if ( "pertest".equalsIgnoreCase( forkMode ) )
- {
- return FORK_ALWAYS;
- }
- else if ( "none".equalsIgnoreCase( forkMode ) )
- {
- return FORK_NEVER;
- }
- else if ( forkMode.equals( FORK_NEVER ) || forkMode.equals( FORK_ONCE )
- || forkMode.equals( FORK_ALWAYS ) || forkMode.equals( FORK_PERTHREAD ) )
- {
- return forkMode;
- }
- else
- {
- throw new IllegalArgumentException( "Fork mode " + forkMode + " is not a legal value" );
- }
- }
+ public static final String DEFAULT_PROVIDER_CLASS = ForkedBooter.class.getName();
+
+ @Nonnull public abstract File getTempDirectory();
+ @Nullable protected abstract String getDebugLine();
+ @Nonnull protected abstract File getWorkingDirectory();
+ @Nonnull protected abstract Properties getModelProperties();
+ @Nullable protected abstract String getArgLine();
+ @Nonnull protected abstract Map<String, String> getEnvironmentVariables();
+ protected abstract boolean isDebug();
+ protected abstract int getForkCount();
+ protected abstract boolean isReuseForks();
+ @Nonnull protected abstract Platform getPluginPlatform();
+ @Nonnull protected abstract JdkAttributes getJdkForTests();
+ @Nonnull protected abstract Classpath getBooterClasspath();
/**
- * @param classPath cli the classpath arguments
* @param config The startup configuration
- * @param threadNumber the thread number, to be the replacement in the argLine @return A commandline
+ * @param forkNumber index of forked JVM, to be the replacement in the argLine
* @return CommandLine able to flush entire command going to be sent to forked JVM
* @throws org.apache.maven.surefire.booter.SurefireBooterForkException
* when unable to perform the fork
*/
- public OutputStreamFlushableCommandline createCommandLine( List<String> classPath, StartupConfiguration config,
- int threadNumber )
- throws SurefireBooterForkException
- {
- boolean useJar = config.getClassLoaderConfiguration().isManifestOnlyJarRequestedAndUsable();
-
- boolean shadefire = config.isShadefire();
-
- String providerThatHasMainMethod =
- config.isProviderMainClass() ? config.getActualClassName() : ForkedBooter.class.getName();
-
- return createCommandLine( classPath, useJar, shadefire, providerThatHasMainMethod, threadNumber );
- }
-
- OutputStreamFlushableCommandline createCommandLine( List<String> classPath, boolean useJar, boolean shadefire,
- String providerThatHasMainMethod, int threadNumber )
- throws SurefireBooterForkException
- {
- OutputStreamFlushableCommandline cli = new OutputStreamFlushableCommandline();
-
- cli.setExecutable( jdk.getJvmExecutable() );
-
- String jvmArgLine =
- replaceThreadNumberPlaceholder( stripNewLines( replacePropertyExpressions() ), threadNumber );
-
- if ( jdk.isJava9AtLeast() && !jvmArgLine.contains( "--add-modules" ) )
- {
- if ( jvmArgLine.isEmpty() )
- {
- jvmArgLine = "--add-modules java.se.ee";
- }
- else
- {
- jvmArgLine = "--add-modules java.se.ee " + jvmArgLine;
- }
- }
-
- if ( !jvmArgLine.isEmpty() )
- {
- cli.createArg().setLine( jvmArgLine );
- }
-
- for ( Map.Entry<String, String> entry : environmentVariables.entrySet() )
- {
- String value = entry.getValue();
- cli.addEnvironment( entry.getKey(), value == null ? "" : value );
- }
-
- if ( getDebugLine() != null && !getDebugLine().isEmpty() )
- {
- cli.createArg().setLine( getDebugLine() );
- }
-
- if ( useJar )
- {
- try
- {
- File jarFile = createJar( classPath, providerThatHasMainMethod );
- cli.createArg().setValue( "-jar" );
- cli.createArg().setValue( escapeToPlatformPath( jarFile.getAbsolutePath() ) );
- }
- catch ( IOException e )
- {
- throw new SurefireBooterForkException( "Error creating archive file", e );
- }
- }
- else
- {
- cli.addEnvironment( "CLASSPATH", join( classPath.iterator(), File.pathSeparator ) );
-
- final String forkedBooter =
- providerThatHasMainMethod != null ? providerThatHasMainMethod : ForkedBooter.class.getName();
-
- cli.createArg().setValue( shadefire ? new Relocator().relocate( forkedBooter ) : forkedBooter );
- }
-
- cli.setWorkingDirectory( getWorkingDirectory( threadNumber ).getAbsolutePath() );
-
- return cli;
- }
-
- private File getWorkingDirectory( int threadNumber )
- throws SurefireBooterForkException
- {
- File cwd = new File( replaceThreadNumberPlaceholder( workingDirectory.getAbsolutePath(), threadNumber ) );
- if ( !cwd.exists() && !cwd.mkdirs() )
- {
- throw new SurefireBooterForkException( "Cannot create workingDirectory " + cwd.getAbsolutePath() );
- }
- if ( !cwd.isDirectory() )
- {
- throw new SurefireBooterForkException(
- "WorkingDirectory " + cwd.getAbsolutePath() + " exists and is not a directory" );
- }
- return cwd;
- }
-
- private String replaceThreadNumberPlaceholder( String argLine, int threadNumber )
- {
- return argLine.replace( AbstractSurefireMojo.THREAD_NUMBER_PLACEHOLDER,
- String.valueOf( threadNumber ) ).replace( AbstractSurefireMojo.FORK_NUMBER_PLACEHOLDER,
- String.valueOf( threadNumber ) );
- }
-
- /**
- * Replaces expressions <pre>@{property-name}</pre> with the corresponding properties
- * from the model. This allows late evaluation of property values when the plugin is executed (as compared
- * to evaluation when the pom is parsed as is done with <pre>${property-name}</pre> expressions).
- *
- * This allows other plugins to modify or set properties with the changes getting picked up by surefire.
- */
- private String replacePropertyExpressions()
- {
- if ( argLine == null )
- {
- return "";
- }
-
- String resolvedArgLine = argLine.trim();
-
- if ( resolvedArgLine.isEmpty() )
- {
- return "";
- }
-
- for ( final String key : modelProperties.stringPropertyNames() )
- {
- String field = "@{" + key + "}";
- if ( argLine.contains( field ) )
- {
- resolvedArgLine = resolvedArgLine.replace( field, modelProperties.getProperty( key, "" ) );
- }
- }
-
- return resolvedArgLine;
- }
-
- /**
- * Create a jar with just a manifest containing a Main-Class entry for BooterConfiguration and a Class-Path entry
- * for all classpath elements.
- *
- * @param classPath List<String> of all classpath elements.
- * @param startClassName The classname to start (main-class)
- * @return The file pointint to the jar
- * @throws java.io.IOException When a file operation fails.
- */
- private File createJar( List<String> classPath, String startClassName )
- throws IOException
- {
- File file = File.createTempFile( "surefirebooter", ".jar", tempDirectory );
- if ( !debug )
- {
- file.deleteOnExit();
- }
- FileOutputStream fos = new FileOutputStream( file );
- JarOutputStream jos = new JarOutputStream( fos );
- try
- {
- jos.setLevel( JarOutputStream.STORED );
- JarEntry je = new JarEntry( "META-INF/MANIFEST.MF" );
- jos.putNextEntry( je );
-
- Manifest man = 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.
- StringBuilder cp = new StringBuilder();
- for ( Iterator<String> it = classPath.iterator(); it.hasNext(); )
- {
- File file1 = new File( it.next() );
- String uri = file1.toURI().toASCIIString();
- cp.append( uri );
- if ( file1.isDirectory() && !uri.endsWith( "/" ) )
- {
- cp.append( '/' );
- }
-
- if ( it.hasNext() )
- {
- cp.append( ' ' );
- }
- }
-
- man.getMainAttributes().putValue( "Manifest-Version", "1.0" );
- man.getMainAttributes().putValue( "Class-Path", cp.toString().trim() );
- man.getMainAttributes().putValue( "Main-Class", startClassName );
-
- man.write( jos );
-
- jos.closeEntry();
- jos.flush();
-
- return file;
- }
- finally
- {
- jos.close();
- }
- }
-
- public boolean isDebug()
- {
- return debug;
- }
-
- public String getDebugLine()
- {
- return debugLine;
- }
-
- public File getTempDirectory()
- {
- return tempDirectory;
- }
-
- public int getForkCount()
- {
- return forkCount;
- }
-
- public boolean isReuseForks()
- {
- return reuseForks;
- }
-
- public Platform getPluginPlatform()
- {
- return pluginPlatform;
- }
-
- private static String stripNewLines( String argLine )
- {
- return argLine.replace( "\n", " " ).replace( "\r", " " );
- }
-
- /**
- * Immutable map.
- *
- * @param map immutable map copies elements from <code>map</code>
- * @param <K> key type
- * @param <V> value type
- * @return never returns null
- */
- private static <K, V> Map<K, V> toImmutable( Map<K, V> map )
- {
- return map == null ? Collections.<K, V>emptyMap() : new ImmutableMap<K, V>( map );
- }
+ @Nonnull
+ public abstract OutputStreamFlushableCommandline createCommandLine( @Nonnull StartupConfiguration config,
+ int forkNumber )
+ throws SurefireBooterForkException;
}
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/f337881f/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java
index 31237b2..a7c0311 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java
@@ -35,8 +35,7 @@ import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
import org.apache.maven.plugin.surefire.report.DefaultReporterFactory;
import org.apache.maven.shared.utils.cli.CommandLineCallable;
import org.apache.maven.shared.utils.cli.CommandLineException;
-import org.apache.maven.surefire.booter.Classpath;
-import org.apache.maven.surefire.booter.ClasspathConfiguration;
+import org.apache.maven.surefire.booter.AbstractPathConfiguration;
import org.apache.maven.surefire.booter.KeyValueSource;
import org.apache.maven.surefire.booter.PropertiesWrapper;
import org.apache.maven.surefire.booter.ProviderConfiguration;
@@ -88,7 +87,6 @@ import static org.apache.maven.plugin.surefire.booterclient.lazytestprovider.Tes
import static org.apache.maven.shared.utils.cli.CommandLineUtils.executeCommandLineAsCallable;
import static org.apache.maven.shared.utils.cli.ShutdownHookUtils.addShutDownHook;
import static org.apache.maven.shared.utils.cli.ShutdownHookUtils.removeShutdownHook;
-import static org.apache.maven.surefire.booter.Classpath.join;
import static org.apache.maven.surefire.booter.SystemPropertyManager.writePropertiesFile;
import static org.apache.maven.surefire.suite.RunResult.SUCCESS;
import static org.apache.maven.surefire.suite.RunResult.failure;
@@ -552,13 +550,11 @@ public class ForkStarter
{
tempDir = forkConfiguration.getTempDirectory().getCanonicalPath();
BooterSerializer booterSerializer = new BooterSerializer( forkConfiguration );
-
+ Long pluginPid = forkConfiguration.getPluginPlatform().getPluginPid();
surefireProperties = booterSerializer.serialize( providerProperties, providerConfiguration,
- startupConfiguration, testSet,
- readTestsFromInStream,
- forkConfiguration.getPluginPlatform().getPid() );
+ startupConfiguration, testSet, readTestsFromInStream, pluginPid );
- log.debug( "Determined Maven Process ID " + forkConfiguration.getPluginPlatform().getPid() );
+ log.debug( "Determined Maven Process ID " + pluginPid );
if ( effectiveSystemProperties != null )
{
@@ -579,20 +575,9 @@ public class ForkStarter
throw new SurefireBooterForkException( "Error creating properties files for forking", e );
}
- // this could probably be simplified further
- final Classpath bootClasspathConfiguration = startupConfiguration.isProviderMainClass()
- ? startupConfiguration.getClasspathConfiguration().getProviderClasspath()
- : forkConfiguration.getBootClasspath();
-
- Classpath bootClasspath = join(
- join( bootClasspathConfiguration, startupConfiguration.getClasspathConfiguration().getTestClasspath() ),
- startupConfiguration.getClasspathConfiguration().getProviderClasspath() );
- log.debug( bootClasspath.getLogMessage( "boot" ) );
- log.debug( bootClasspath.getCompactLogMessage( "boot(compact)" ) );
- OutputStreamFlushableCommandline cli =
- forkConfiguration.createCommandLine( bootClasspath.getClassPath(), startupConfiguration, forkNumber );
+ OutputStreamFlushableCommandline cli = forkConfiguration.createCommandLine( startupConfiguration, forkNumber );
if ( testProvidingInputStream != null )
{
@@ -701,7 +686,7 @@ public class ForkStarter
{
try
{
- final ClasspathConfiguration classpathConfiguration = startupConfiguration.getClasspathConfiguration();
+ AbstractPathConfiguration classpathConfiguration = startupConfiguration.getClasspathConfiguration();
ClassLoader unifiedClassLoader = classpathConfiguration.createMergedClassLoader();
CommonReflector commonReflector = new CommonReflector( unifiedClassLoader );
http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/f337881f/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/JarManifestForkConfiguration.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/JarManifestForkConfiguration.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/JarManifestForkConfiguration.java
new file mode 100644
index 0000000..0c19cdf
--- /dev/null
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/JarManifestForkConfiguration.java
@@ -0,0 +1,139 @@
+package org.apache.maven.plugin.surefire.booterclient;
+
+/*
+ * 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.plugin.surefire.booterclient.lazytestprovider.OutputStreamFlushableCommandline;
+import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
+import org.apache.maven.surefire.booter.Classpath;
+import org.apache.maven.surefire.booter.StartupConfiguration;
+import org.apache.maven.surefire.booter.SurefireBooterForkException;
+
+import javax.annotation.Nonnull;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.jar.JarEntry;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+
+import static org.apache.maven.plugin.surefire.SurefireHelper.escapeToPlatformPath;
+
+/**
+ * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
+ * @since 2.21.0.Jigsaw
+ */
+public final class JarManifestForkConfiguration
+ extends AbstractClasspathForkConfiguration
+{
+ @SuppressWarnings( "checkstyle:parameternumber" )
+ public JarManifestForkConfiguration( Classpath bootClasspath, File tempDirectory, String debugLine,
+ File workingDirectory, Properties modelProperties, String argLine,
+ Map<String, String> environmentVariables, boolean debug, int forkCount,
+ boolean reuseForks, Platform pluginPlatform, ConsoleLogger log )
+ {
+ super( bootClasspath, tempDirectory, debugLine, workingDirectory, modelProperties, argLine,
+ environmentVariables, debug, forkCount, reuseForks, pluginPlatform, log );
+ }
+
+ @Override
+ protected void resolveClasspath( OutputStreamFlushableCommandline cli, String booterThatHasMainMethod,
+ StartupConfiguration config )
+ throws SurefireBooterForkException
+ {
+ try
+ {
+ File jar = createJar( toCompleteClasspath( config ), booterThatHasMainMethod );
+ cli.createArg().setValue( "-jar" );
+ cli.createArg().setValue( escapeToPlatformPath( jar.getAbsolutePath() ) );
+ }
+ catch ( IOException e )
+ {
+ throw new SurefireBooterForkException( "Error creating archive file", e );
+ }
+ }
+
+ /**
+ * Create a jar with just a manifest containing a Main-Class entry for BooterConfiguration and a Class-Path entry
+ * for all classpath elements.
+ *
+ * @param classPath List<String> of all classpath elements.
+ * @param startClassName The class name to start (main-class)
+ * @return file of the jar
+ * @throws IOException When a file operation fails.
+ */
+ @Nonnull
+ private File createJar( @Nonnull List<String> classPath, @Nonnull String startClassName )
+ throws IOException
+ {
+ File file = File.createTempFile( "surefirebooter", ".jar", getTempDirectory() );
+ if ( !isDebug() )
+ {
+ file.deleteOnExit();
+ }
+ FileOutputStream fos = new FileOutputStream( file );
+ JarOutputStream jos = new JarOutputStream( fos );
+ try
+ {
+ jos.setLevel( JarOutputStream.STORED );
+ JarEntry je = new JarEntry( "META-INF/MANIFEST.MF" );
+ jos.putNextEntry( je );
+
+ Manifest man = 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.
+ StringBuilder cp = new StringBuilder();
+ for ( Iterator<String> it = classPath.iterator(); it.hasNext(); )
+ {
+ File file1 = new File( it.next() );
+ String uri = file1.toURI().toASCIIString();
+ cp.append( uri );
+ if ( file1.isDirectory() && !uri.endsWith( "/" ) )
+ {
+ cp.append( '/' );
+ }
+
+ if ( it.hasNext() )
+ {
+ cp.append( ' ' );
+ }
+ }
+
+ man.getMainAttributes().putValue( "Manifest-Version", "1.0" );
+ man.getMainAttributes().putValue( "Class-Path", cp.toString().trim() );
+ man.getMainAttributes().putValue( "Main-Class", startClassName );
+
+ man.write( jos );
+
+ jos.closeEntry();
+ jos.flush();
+
+ return file;
+ }
+ finally
+ {
+ jos.close();
+ }
+ }
+}