// CHECKSTYLE_OFF: FileLength|RegexpHeader
package org.apache.maven.plugin.surefire;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.DefaultArtifact;
import org.apache.maven.artifact.handler.ArtifactHandler;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.model.Plugin;
import org.apache.maven.plugin.surefire.extensions.LegacyForkNodeFactory;
import org.apache.maven.plugin.surefire.extensions.SurefireConsoleOutputReporter;
import org.apache.maven.plugin.surefire.extensions.SurefireStatelessReporter;
import org.apache.maven.plugin.surefire.extensions.SurefireStatelessTestsetInfoReporter;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.project.ProjectBuildingRequest;
import org.apache.maven.repository.RepositorySystem;
import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
import org.apache.maven.artifact.versioning.VersionRange;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.apache.maven.plugin.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;
import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
import org.apache.maven.plugin.surefire.util.DependencyScanner;
import org.apache.maven.plugin.surefire.util.DirectoryScanner;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.apache.maven.shared.artifact.filter.PatternIncludesArtifactFilter;
import org.apache.maven.shared.transfer.dependencies.resolve.DependencyResolver;
import org.apache.maven.surefire.shared.utils.io.FileUtils;
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.ProcessCheckerType;
import org.apache.maven.surefire.booter.ProviderConfiguration;
import org.apache.maven.surefire.api.booter.ProviderParameterNames;
import org.apache.maven.surefire.api.booter.Shutdown;
import org.apache.maven.surefire.booter.StartupConfiguration;
import org.apache.maven.surefire.booter.SurefireBooterForkException;
import org.apache.maven.surefire.booter.SurefireExecutionException;
import org.apache.maven.surefire.api.cli.CommandLineOption;
import org.apache.maven.surefire.extensions.ForkNodeFactory;
import org.apache.maven.surefire.api.provider.SurefireProvider;
import org.apache.maven.surefire.api.report.ReporterConfiguration;
import org.apache.maven.surefire.api.suite.RunResult;
import org.apache.maven.surefire.api.testset.DirectoryScannerParameters;
import org.apache.maven.surefire.api.testset.RunOrderParameters;
import org.apache.maven.surefire.api.testset.TestArtifactInfo;
import org.apache.maven.surefire.api.testset.TestListResolver;
import org.apache.maven.surefire.api.testset.TestRequest;
import org.apache.maven.surefire.api.testset.TestSetFailedException;
import org.apache.maven.surefire.api.util.DefaultScanResult;
import org.apache.maven.surefire.api.util.RunOrder;
import org.apache.maven.toolchain.DefaultToolchain;
import org.apache.maven.toolchain.Toolchain;
import org.apache.maven.toolchain.ToolchainManager;
import org.apache.maven.toolchain.java.DefaultJavaToolChain;
import org.codehaus.plexus.languages.java.jpms.ResolvePathRequest;
import org.codehaus.plexus.languages.java.jpms.ResolvePathResult;
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;
import java.io.IOException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
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.Boolean.TRUE;
import static java.lang.Integer.parseInt;
import static java.lang.Thread.currentThread;
import static java.util.Arrays.asList;
import static java.util.Collections.addAll;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap;
import static org.apache.maven.surefire.shared.lang3.StringUtils.substringBeforeLast;
import static org.apache.maven.surefire.shared.lang3.SystemUtils.IS_OS_WINDOWS;
import static org.apache.maven.plugin.surefire.SurefireDependencyResolver.isWithinVersionSpec;
import static org.apache.maven.plugin.surefire.util.DependencyScanner.filter;
import static org.apache.maven.plugin.surefire.SurefireHelper.replaceThreadNumberPlaceholders;
import static org.apache.maven.surefire.shared.utils.StringUtils.capitalizeFirstLetter;
import static org.apache.maven.surefire.shared.utils.StringUtils.isEmpty;
import static org.apache.maven.surefire.shared.utils.StringUtils.isNotBlank;
import static org.apache.maven.surefire.shared.utils.StringUtils.isNotEmpty;
import static org.apache.maven.surefire.shared.utils.StringUtils.split;
import static org.apache.maven.surefire.booter.SystemUtils.JAVA_SPECIFICATION_VERSION;
import static org.apache.maven.surefire.booter.SystemUtils.endsWithJavaPath;
import static org.apache.maven.surefire.booter.SystemUtils.isBuiltInJava9AtLeast;
import static org.apache.maven.surefire.booter.SystemUtils.isJava9AtLeast;
import static org.apache.maven.surefire.booter.SystemUtils.toJdkHomeFromJvmExec;
import static org.apache.maven.surefire.booter.SystemUtils.toJdkVersionFromReleaseFile;
import static org.apache.maven.surefire.api.suite.RunResult.failure;
import static org.apache.maven.surefire.api.suite.RunResult.noTestsRun;
import static org.apache.maven.surefire.api.util.ReflectionUtils.invokeMethodWithArray;
import static org.apache.maven.surefire.api.util.ReflectionUtils.tryGetMethod;

/**
 * Abstract base class for running tests using Surefire.
 *
 * @author Stephen Connolly
 * @version $Id: SurefirePlugin.java 945065 2010-05-17 10:26:22Z stephenc $
 */
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 final ProviderDetector providerDetector = new ProviderDetector();

    private final ClasspathCache classpathCache = new ClasspathCache();

    /**
     * Note: use the legacy system property <em>disableXmlReport</em> set to {@code true} to disable the report.
     */
    @Parameter
    private SurefireStatelessReporter statelessTestsetReporter;

    @Parameter
    private SurefireConsoleOutputReporter consoleOutputReporter;

    @Parameter
    private SurefireStatelessTestsetInfoReporter statelessTestsetInfoReporter;

    /**
     * Information about this plugin, mainly used to lookup this plugin's configuration from the currently executing
     * project.
     *
     * @since 2.12
     */
    @Parameter( defaultValue = "${plugin}", readonly = true, required = true )
    private PluginDescriptor pluginDescriptor;

    /**
     * Set this to "true" to skip running tests, but still compile them. Its use is NOT RECOMMENDED, but quite
     * convenient on occasion.<br>
     * Failsafe plugin deprecated the parameter {@code skipTests} and the parameter will be removed in
     * <i>Failsafe 3.0.0</i> as it is a source of conflicts between Failsafe and Surefire plugin.
     *
     * @since 2.4
     */
    @Parameter( property = "skipTests", defaultValue = "false" )
    protected boolean skipTests;

    /**
     * This old parameter is just like {@code skipTests}, but bound to the old property "maven.test.skip.exec".
     *
     * @since 2.3
     * @deprecated Use skipTests instead.
     */
    @Deprecated
    @Parameter( property = "maven.test.skip.exec" )
    protected boolean skipExec;

    /**
     * Set this to "true" to bypass unit tests entirely. Its use is NOT RECOMMENDED, especially if you enable it using
     * the "maven.test.skip" property, because maven.test.skip disables both running the tests and compiling the tests.
     * Consider using the {@code skipTests} parameter instead.
     */
    @Parameter( property = "maven.test.skip", defaultValue = "false" )
    protected boolean skip;

    /**
     * The Maven Project Object.
     */
    @Parameter( defaultValue = "${project}", required = true, readonly = true )
    private MavenProject project;

    /**
     * The base directory of the project being tested. This can be obtained in your integration test via
     * System.getProperty("basedir").
     */
    @Parameter( defaultValue = "${basedir}", readonly = true, required = true )
    protected File basedir;

    /**
     * The directory containing generated test classes of the project being tested. This will be included at the
     * beginning of the test classpath. *
     */
    @Parameter( defaultValue = "${project.build.testOutputDirectory}" )
    protected File testClassesDirectory;

    /**
     * List of dependencies to exclude from the test classpath. Each dependency string must follow the format
     * <i>groupId:artifactId</i>. For example: <i>org.acme:project-a</i>
     *
     * @since 2.6
     */
    @Parameter( property = "maven.test.dependency.excludes" )
    private String[] classpathDependencyExcludes;

    /**
     * A dependency scope to exclude from the test classpath. The scope should be one of the scopes defined by
     * org.apache.maven.artifact.Artifact. This includes the following:
     * <br>
     * <ul>
     * <li><i>compile</i> - system, provided, compile
     * <li><i>runtime</i> - compile, runtime
     * <li><i>compile+runtime</i> - system, provided, compile, runtime
     * <li><i>runtime+system</i> - system, compile, runtime
     * <li><i>test</i> - system, provided, compile, runtime, test
     * </ul>
     *
     * @since 2.6
     */
    @Parameter( defaultValue = "" )
    private String classpathDependencyScopeExclude;

    /**
     * Additional elements to be appended to the classpath.
     *
     * @since 2.4
     */
    @Parameter( property = "maven.test.additionalClasspath" )
    private String[] additionalClasspathElements;

    /**
     * The test source directory containing test class sources.
     *
     * @since 2.2
     */
    @Parameter( defaultValue = "${project.build.testSourceDirectory}", required = true )
    private File testSourceDirectory;

    /**
     * A list of &lt;exclude&gt; elements specifying the tests (by pattern) that should be excluded in testing. When not
     * specified and when the {@code test} parameter is not specified, the default excludes will be <br>
     * <pre><code>
     * {@literal <excludes>}
     *     {@literal <exclude>}**{@literal /}*$*{@literal </exclude>}
     * {@literal </excludes>}
     * </code></pre>
     * (which excludes all inner classes).
     * <br>
     * This parameter is ignored if the TestNG {@code suiteXmlFiles} parameter is specified.
     * <br>
     * Each exclude item may also contain a comma-separated sub-list of items, which will be treated as multiple
     * &nbsp;&lt;exclude&gt; entries.<br>
     * Since 2.19 a complex syntax is supported in one parameter (JUnit 4, JUnit 4.7+, TestNG):
     * <pre><code>
     * {@literal <exclude>}%regex[pkg.*Slow.*.class], Unstable*{@literal </exclude>}
     * </code></pre>
     * <br>
     * <b>Notice that</b> these values are relative to the directory containing generated test classes of the project
     * being tested. This directory is declared by the parameter {@code testClassesDirectory} which defaults
     * to the POM property <code>${project.build.testOutputDirectory}</code>, typically
     * <code>{@literal src/test/java}</code> unless overridden.
     */
    @Parameter
    // TODO use regex for fully qualified class names in 3.0 and change the filtering abilities
    private List<String> excludes;

    /**
     * ArtifactRepository of the localRepository. To obtain the directory of localRepository in unit tests use
     * System.getProperty("localRepository").
     */
    @Parameter( defaultValue = "${localRepository}", required = true, readonly = true )
    private ArtifactRepository localRepository;

    /**
     * List of System properties to pass to the JUnit tests.
     *
     * @deprecated Use systemPropertyVariables instead.
     */
    @Deprecated
    @Parameter
    private Properties systemProperties;

    /**
     * List of System properties to pass to the JUnit tests.
     *
     * @since 2.5
     */
    @Parameter
    private Map<String, String> systemPropertyVariables;

    /**
     * List of properties for configuring all TestNG related configurations. This is the new preferred method of
     * configuring TestNG.
     *
     * @since 2.4
     */
    @Parameter
    private Properties properties;

    /**
     * Map of plugin artifacts.
     */
    @Parameter( property = "plugin.artifactMap", required = true, readonly = true )
    private Map<String, Artifact> pluginArtifactMap;

    /**
     * Map of project artifacts.
     */
    @Parameter( property = "project.artifactMap", readonly = true, required = true )
    private Map<String, Artifact> projectArtifactMap;

    /**
     * Add custom text into report filename: TEST-testClassName-reportNameSuffix.xml,
     * testClassName-reportNameSuffix.txt and testClassName-reportNameSuffix-output.txt.
     * File TEST-testClassName-reportNameSuffix.xml has changed attributes 'testsuite'--'name'
     * and 'testcase'--'classname' - reportNameSuffix is added to the attribute value.
     */
    @Parameter( property = "surefire.reportNameSuffix", defaultValue = "" )
    private String reportNameSuffix;

    /**
     * Set this to "true" to redirect the unit test standard output to a file (found in
     * reportsDirectory/testName-output.txt).
     *
     * @since 2.3
     */
    @Parameter( property = "maven.test.redirectTestOutputToFile", defaultValue = "false" )
    private boolean redirectTestOutputToFile;

    /**
     * Set this to "true" to cause a failure if there are no tests to run. Defaults to "false".
     *
     * @since 2.4
     */
    @Parameter( property = "failIfNoTests" )
    private Boolean failIfNoTests;

    /**
     * <strong>DEPRECATED</strong> since version 2.14. Use {@code forkCount} and {@code reuseForks} instead.
     * <br>
     * <br>
     * Option to specify the forking mode. Can be {@code never}, {@code once}, {@code always}, {@code perthread}.<br>
     * The {@code none} and {@code pertest} are also accepted for backwards compatibility.<br>
     * The {@code always} forks for each test-class.<br>
     * The {@code perthread} creates the number of parallel forks specified by {@code threadCount}, where each forked
     * JVM is executing one test-class. See also the parameter {@code reuseForks} for the lifetime of JVM.
     *
     * @since 2.1
     */
    @Parameter( property = "forkMode", defaultValue = "once" )
    private String forkMode;

    /**
     * Relative path to <i>temporary-surefire-boot</i> directory containing internal Surefire temporary files.
     * <br>
     * The <i>temporary-surefire-boot</i> directory is <i>project.build.directory</i> on most platforms or
     * <i>system default temporary-directory</i> specified by the system property {@code java.io.tmpdir}
     * on Windows (see <a href="https://issues.apache.org/jira/browse/SUREFIRE-1400">SUREFIRE-1400</a>).
     * <br>
     * It is deleted after the test set has completed.
     *
     * @since 2.20
     */
    @Parameter( property = "tempDir", defaultValue = "surefire" )
    private String tempDir;

    /**
     * Option to specify the jvm (or path to the java executable) to use with the forking options. For the default, the
     * jvm will be a new instance of the same VM as the one used to run Maven. JVM settings are not inherited from
     * MAVEN_OPTS.
     *
     * @since 2.1
     */
    @Parameter( property = "jvm" )
    private String jvm;

    /**
     * Arbitrary JVM options to set on the command line.
     * <br>
     * <br>
     * Since the Version 2.17 using an alternate syntax for {@code argLine}, <b>@{...}</b> allows late replacement
     * of properties when the plugin is executed, so properties that have been modified by other plugins will be picked
     * up correctly.
     * See the Frequently Asked Questions page with more details:<br>
     * <a href="http://maven.apache.org/surefire/maven-surefire-plugin/faq.html">
     *     http://maven.apache.org/surefire/maven-surefire-plugin/faq.html</a>
     * <br>
     * <a href="http://maven.apache.org/surefire/maven-failsafe-plugin/faq.html">
     *     http://maven.apache.org/surefire/maven-failsafe-plugin/faq.html</a>
     *
     * @since 2.1
     */
    @Parameter( property = "argLine" )
    private String argLine;

    /**
     * Additional environment variables to set on the command line.
     *
     * @since 2.1.3
     */
    @Parameter
    private Map<String, String> environmentVariables = new HashMap<>();

    /**
     * Command line working directory.
     *
     * @since 2.1.3
     */
    @Parameter( property = "basedir" )
    private File workingDirectory;

    /**
     * When false it makes tests run using the standard classloader delegation instead of the default Maven isolated
     * classloader. Only used when forking ({@code forkMode} is not {@code none}).<br>
     * Setting it to false helps with some problems caused by conflicts between xml parsers in the classpath and the
     * Java 5 provider parser.
     *
     * @since 2.1
     */
    @Parameter( property = "childDelegation", defaultValue = "false" )
    private boolean childDelegation;

    /**
     * (TestNG/JUnit47 provider with JUnit4.8+ only and JUnit5+ provider since 2.22.0) Groups/categories/tags for this
     * test. Only classes/methods/etc decorated with one of the groups/categories/tags specified here will be included
     * in test run, if specified.<br>
     * For JUnit4 tests, this parameter forces the use of the 4.7 provider. For JUnit5 tests, this parameter forces
     * the use of the JUnit platform provider.<br>
     * This parameter is ignored if the {@code suiteXmlFiles} parameter is specified.<br>
     * Since version 2.18.1 and JUnit 4.12, the {@code @Category} annotation type is automatically inherited from
     * superclasses, see {@code @java.lang.annotation.Inherited}. Make sure that test class inheritance still makes
     * sense together with {@code @Category} annotation of the JUnit 4.12 or higher appeared in superclass.
     *
     * @since 2.2
     */
    @Parameter( property = "groups" )
    private String groups;

    /**
     * (TestNG/JUnit47 provider with JUnit4.8+ only and JUnit5+ provider since 2.22.0) Excluded groups/categories/tags.
     * Any methods/classes/etc with one of the groups/categories/tags specified in this list will specifically not be
     * run.<br>
     * For JUnit4, this parameter forces the use of the 4.7 provider. For JUnit5, this parameter forces the use of the
     * JUnit platform provider.<br>
     * This parameter is ignored if the {@code suiteXmlFiles} parameter is specified.<br>
     * Since version 2.18.1 and JUnit 4.12, the {@code @Category} annotation type is automatically inherited from
     * superclasses, see {@code @java.lang.annotation.Inherited}. Make sure that test class inheritance still makes
     * sense together with {@code @Category} annotation of the JUnit 4.12 or higher appeared in superclass.
     *
     * @since 2.2
     */
    @Parameter( property = "excludedGroups" )
    private String excludedGroups;

    /**
     * Allows you to specify the name of the JUnit artifact. If not set, {@code junit:junit} will be used.
     *
     * @since 2.3.1
     */
    @Parameter( property = "junitArtifactName", defaultValue = "junit:junit" )
    private String junitArtifactName;

    /**
     * Allows you to specify the name of the TestNG artifact. If not set, {@code org.testng:testng} will be used.
     *
     * @since 2.3.1
     */
    @Parameter( property = "testNGArtifactName", defaultValue = "org.testng:testng" )
    private String testNGArtifactName;

    /**
     * (TestNG/JUnit 4.7 provider) The attribute thread-count allows you to specify how many threads should be
     * allocated for this execution. Only makes sense to use in conjunction with the {@code parallel} parameter.
     *
     * @since 2.2
     */
    @Parameter( property = "threadCount" )
    private int threadCount;

    /**
     * Option to specify the number of VMs to fork in parallel in order to execute the tests. When terminated with "C",
     * the number part is multiplied with the number of CPU cores. Floating point value are only accepted together with
     * "C". If set to "0", no VM is forked and all tests are executed within the main process.<br>
     * <br>
     * Example values: "1.5C", "4"<br>
     * <br>
     * The system properties and the {@code argLine} of the forked processes may contain the place holder string
     * <code>${surefire.forkNumber}</code>, which is replaced with a fixed number for each of the parallel forks,
     * ranging from <b>1</b> to the effective value of {@code forkCount} times the maximum number of parallel
     * Surefire executions in maven parallel builds, i.e. the effective value of the <b>-T</b> command line
     * argument of maven core.
     *
     * @since 2.14
     */
    @Parameter( property = "forkCount", defaultValue = "1" )
    private String forkCount;

    /**
     * Indicates if forked VMs can be reused. If set to "false", a new VM is forked for each test class to be executed.
     * If set to "true", up to {@code forkCount} VMs will be forked and then reused to execute all tests.
     *
     * @since 2.13
     */

    @Parameter( property = "reuseForks", defaultValue = "true" )
    private boolean reuseForks;

    /**
     * (JUnit 4.7 provider) Indicates that threadCount, threadCountSuites, threadCountClasses, threadCountMethods
     * are per cpu core.
     *
     * @since 2.5
     */
    @Parameter( property = "perCoreThreadCount", defaultValue = "true" )
    private boolean perCoreThreadCount;

    /**
     * (JUnit 4.7 provider) Indicates that the thread pool will be unlimited. The {@code parallel} parameter and
     * the actual number of classes/methods will decide. Setting this to "true" effectively disables
     * {@code perCoreThreadCount} and {@code threadCount}. Defaults to "false".
     *
     * @since 2.5
     */
    @Parameter( property = "useUnlimitedThreads", defaultValue = "false" )
    private boolean useUnlimitedThreads;

    /**
     * (TestNG provider) When you use the parameter {@code parallel}, TestNG will try to run all your test methods
     * in separate threads, except for methods that depend on each other, which will be run in the same thread in order
     * to respect their order of execution.
     * <br>
     * (JUnit 4.7 provider) Supports values {@code classes}, {@code methods}, {@code both} to run
     * in separate threads been controlled by {@code threadCount}.
     * <br>
     * <br>
     * Since version 2.16 (JUnit 4.7 provider), the value {@code both} is <strong>DEPRECATED</strong>.
     * Use {@code classesAndMethods} instead.
     * <br>
     * <br>
     * Since version 2.16 (JUnit 4.7 provider), additional vales are available:
     * <br>
     * {@code suites}, {@code suitesAndClasses}, {@code suitesAndMethods}, {@code classesAndMethods}, {@code all}.
     * <br>
     * By default, Surefire does not execute tests in parallel. You can set the parameter {@code parallel} to
     * {@code none} to explicitly disable parallel execution (e.g. when disabling parallel execution in special Maven
     * profiles when executing coverage analysis).
     *
     * @since 2.2
     */
    @Parameter( property = "parallel" )
    private String parallel;

    /**
     * (JUnit 4.7 / provider only) The thread counts do not exceed the number of parallel suite, class runners and
     * average number of methods per class if set to <strong>true</strong>.
     * <br>
     * True by default.
     *
     * @since 2.17
     */
    @Parameter( property = "parallelOptimized", defaultValue = "true" )
    private boolean parallelOptimized;

    /**
     * (JUnit 4.7 provider) This attribute allows you to specify the concurrency in test suites, i.e.:
     * <ul>
     *  <li>number of concurrent suites if {@code threadCount} is 0 or unspecified</li>
     *  <li>limited suites concurrency if {@code useUnlimitedThreads} is set to <strong>true</strong></li>
     *  <li>if {@code threadCount} and certain thread-count parameters are &gt; 0 for {@code parallel}, the
     *  concurrency is computed from ratio. For instance {@code parallel=all} and the ratio between
     *      {@code threadCountSuites}:{@code threadCountClasses}:{@code threadCountMethods} is
     *      <b>2</b>:3:5, there is 20% of {@code threadCount} which appeared in concurrent suites.</li>
     * </ul>
     *
     * Only makes sense to use in conjunction with the {@code parallel} parameter.
     * The default value <b>0</b> behaves same as unspecified one.
     *
     * @since 2.16
     */
    @Parameter( property = "threadCountSuites", defaultValue = "0" )
    private int threadCountSuites;

    /**
     * (JUnit 4.7 provider) This attribute allows you to specify the concurrency in test classes, i.e.:
     * <ul>
     *  <li>number of concurrent classes if {@code threadCount} is 0 or unspecified</li>
     *  <li>limited classes concurrency if {@code useUnlimitedThreads} is set to <strong>true</strong></li>
     *  <li>if {@code threadCount} and certain thread-count parameters are &gt; 0 for {@code parallel}, the
     *  concurrency is computed from ratio. For instance {@code parallel=all} and the ratio between
     *      {@code threadCountSuites}:{@code threadCountClasses}:{@code threadCountMethods} is
     *      2:<b>3</b>:5, there is 30% of {@code threadCount} in concurrent classes.</li>
     *  <li>as in the previous case but without this leaf thread-count. Example: {@code parallel=suitesAndClasses},
     *  {@code threadCount=16}, {@code threadCountSuites=5}, {@code threadCountClasses} is unspecified leaf, the number
     *  of concurrent classes is varying from &gt;= 11 to 14 or 15. The {@code threadCountSuites} become
     *  given number of threads.</li>
     * </ul>
     *
     * Only makes sense to use in conjunction with the {@code parallel} parameter.
     * The default value <b>0</b> behaves same as unspecified one.
     *
     * @since 2.16
     */
    @Parameter( property = "threadCountClasses", defaultValue = "0" )
    private int threadCountClasses;

    /**
     * (JUnit 4.7 provider) This attribute allows you to specify the concurrency in test methods, i.e.:
     * <ul>
     * <li>number of concurrent methods if {@code threadCount} is 0 or unspecified</li>
     * <li>limited concurrency of methods if {@code useUnlimitedThreads} is set to <strong>true</strong></li>
     * <li>if {@code threadCount} and certain thread-count parameters are &gt; 0 for {@code parallel}, the
     * concurrency is computed from ratio. For instance parallel=all and the ratio between
     * {@code threadCountSuites}:{@code threadCountClasses}:{@code threadCountMethods} is 2:3:<b>5</b>,
     * there is 50% of {@code threadCount} which appears in concurrent methods.</li>
     * <li>as in the previous case but without this leaf thread-count. Example: {@code parallel=all},
     * {@code threadCount=16}, {@code threadCountSuites=2}, {@code threadCountClasses=3}, but {@code threadCountMethods}
     * is unspecified leaf, the number of concurrent methods is varying from &gt;= 11 to 14 or 15.
     * The {@code threadCountSuites} and {@code threadCountClasses} become given number of threads.</li>
     * </ul>
     * Only makes sense to use in conjunction with the {@code parallel} parameter. The default value <b>0</b>
     * behaves same as unspecified one.
     *
     * @since 2.16
     */
    @Parameter( property = "threadCountMethods", defaultValue = "0" )
    private int threadCountMethods;

    /**
     * Whether to trim the stack trace in the reports to just the lines within the test, or show the full trace.
     *
     * @since 2.2
     */
    @Parameter( property = "trimStackTrace", defaultValue = "true" )
    private boolean trimStackTrace;

    /**
     * The remote plugin repositories declared in the POM.
     *
     * @since 2.2
     */
    @Parameter( defaultValue = "${project.pluginArtifactRepositories}", readonly = true, required = true )
    private List<ArtifactRepository> remoteRepositories;

    @Parameter( defaultValue = "${project.remoteArtifactRepositories}", required = true, readonly = true )
    private List<ArtifactRepository> projectRemoteRepositories;

    /**
     * Flag to disable the generation of report files in xml format.
     * Deprecated since 3.0.0-M4.
     * Instead use <em>disable</em> within {@code statelessTestsetReporter} since of 3.0.0-M6.
     * @since 2.2
     */
    @Deprecated // todo make readonly to handle system property
    @Parameter( property = "disableXmlReport", defaultValue = "false" )
    private boolean disableXmlReport;

    /**
     * By default, Surefire enables JVM assertions for the execution of your test cases. To disable the assertions, set
     * this flag to "false".
     *
     * @since 2.3.1
     */
    @Parameter( property = "enableAssertions", defaultValue = "true" )
    private boolean enableAssertions;

    /**
     * The current build session instance.
     */
    @Parameter( defaultValue = "${session}", required = true, readonly = true )
    private MavenSession session;

    @Component
    private Logger logger;

    /**
     * (TestNG only) Define the factory class used to create all test instances.
     *
     * @since 2.5
     */
    @Parameter( property = "objectFactory" )
    private String objectFactory;

    /**
     * Parallel Maven Execution.
     */
    @Parameter( defaultValue = "${session.parallel}", readonly = true )
    private Boolean parallelMavenExecution;

    /**
     * Read-only parameter with value of Maven property <i>project.build.directory</i>.
     * @since 2.20
     */
    @Parameter( defaultValue = "${project.build.directory}", readonly = true, required = true )
    private File projectBuildDirectory;

    /**
     * List of dependencies to scan for test classes to include in the test run.
     * The child elements of this element must be &lt;dependency&gt; elements, and the
     * contents of each of these elements must be a string which follows the general form:
     *
     * <p>{@code groupId[:artifactId[:type[:classifier][:version]]]}</p>
     *
     * <p>The wildcard character <code>*</code> can be used within the sub parts of those composite identifiers to
     * do glob-like pattern matching. The classifier may be omitted when matching dependencies without a classifier.</p>
     *
     * <p>Examples:</p>
     *
     * <ul>
     *     <li>{@code group} or, equivalently, {@code group:*}</li>
     *     <li>{@code g*p:*rtifac*}</li>
     *     <li>{@code group:*:jar}</li>
     *     <li>{@code group:artifact:*:1.0.0} (no classifier)</li>
     *     <li>{@code group:*:test-jar:tests}</li>
     *     <li>{@code *:artifact:*:*:1.0.0}</li>
     * </ul>
     *
     * <p>Since version 2.22.0 you can scan for test classes from a project
     * dependency of your multi-module project.</p>
     *
     * <p>In versions before 3.0.0-M4, only <code>groupId:artifactId</code> is supported.</p>
     *
     * @since 2.15
     */
    @Parameter( property = "dependenciesToScan" )
    private String[] dependenciesToScan;

    /**
     * <p>
     *     Allow for configuration of the test jvm via maven toolchains.
     *     This permits a configuration where the project is built with one jvm and tested with another.
     *     This is similar to {@link #jvm}, but avoids hardcoding paths.
     *     The two parameters are mutually exclusive (jvm wins)
     * </p>
     *
     * <p>Examples:</p>
     * (see <a href="https://maven.apache.org/guides/mini/guide-using-toolchains.html">
     *     Guide to Toolchains</a> for more info)
     *
     * <pre>
     * {@code
     *    <configuration>
     *        ...
     *        <jdkToolchain>
     *            <version>1.11</version>
     *        </jdkToolchain>
     *    </configuration>
     *
     *    <configuration>
     *        ...
     *        <jdkToolchain>
     *            <version>1.8</version>
     *            <vendor>zulu</vendor>
     *        </jdkToolchain>
     *    </configuration>
     *    }
     * </pre>
     *
     * @since 3.0.0-M5 and Maven 3.3.x
     */
    @Parameter
    private Map<String, String> jdkToolchain;

    /**
     *
     */
    @Component
    private ToolchainManager toolchainManager;

    @Component
    private LocationManager locationManager;

    @Component
    private RepositorySystem repositorySystem;

    @Component
    private DependencyResolver dependencyResolver;

    private Toolchain toolchain;

    private int effectiveForkCount = -1;

    protected abstract String getPluginName();

    protected abstract int getRerunFailingTestsCount();

    @Override
    public abstract List<String> getIncludes();

    public abstract File getIncludesFile();

    @Override
    public abstract void setIncludes( List<String> includes );

    public abstract File getExcludesFile();

    /**
     * Calls {@link #getSuiteXmlFiles()} as {@link List list}.
     * Never returns <tt>null</tt>.
     *
     * @return list of TestNG suite XML files provided by MOJO
     */
    protected abstract List<File> suiteXmlFiles();

    /**
     * @return {@code true} if {@link #getSuiteXmlFiles() suite-xml files array} is not empty.
     */
    protected abstract boolean hasSuiteXmlFiles();

    protected abstract String[] getExcludedEnvironmentVariables();

    public abstract File[] getSuiteXmlFiles();

    public abstract void setSuiteXmlFiles( File[] suiteXmlFiles );

    public abstract String getRunOrder();

    public abstract void setRunOrder( String runOrder );

    protected abstract void handleSummary( RunResult summary, Exception firstForkException )
        throws MojoExecutionException, MojoFailureException;

    protected abstract boolean isSkipExecution();

    protected abstract String[] getDefaultIncludes();

    protected abstract String getReportSchemaLocation();

    protected abstract boolean useModulePath();

    protected abstract void setUseModulePath( boolean useModulePath );

    protected abstract String getEnableProcessChecker();

    protected abstract ForkNodeFactory getForkNode();

    /**
     * This plugin MOJO artifact.
     *
     * @return non-null plugin artifact
     */
    protected Artifact getMojoArtifact()
    {
        return getPluginDescriptor().getPluginArtifact();
    }

    private String getDefaultExcludes()
    {
        return "**/*$*";
    }

    private SurefireDependencyResolver surefireDependencyResolver;

    private TestListResolver specificTests;

    private TestListResolver includedExcludedTests;

    private List<CommandLineOption> cli;

    private volatile PluginConsoleLogger consoleLogger;

    @Override
    public void execute()
        throws MojoExecutionException, MojoFailureException
    {
        cli = commandLineOptions();
        // Stuff that should have been final
        setupStuff();
        Platform platform = PLATFORM.withJdkExecAttributesForTests( getEffectiveJvm() );

        if ( verifyParameters() && !hasExecutedBefore() )
        {
            DefaultScanResult scan = scanForTestClasses();
            if ( !hasSuiteXmlFiles() && scan.isEmpty() )
            {
                if ( getEffectiveFailIfNoTests() )
                {
                    throw new MojoFailureException(
                        "No tests were executed!  (Set -DfailIfNoTests=false to ignore this error.)" );
                }
                handleSummary( noTestsRun(), null );
                return;
            }
            logReportsDirectory();
            executeAfterPreconditionsChecked( scan, platform );
        }
    }

    void setLogger( Logger logger )
    {
        this.logger = logger;
    }

    @Nonnull
    protected final PluginConsoleLogger getConsoleLogger()
    {
        if ( consoleLogger == null )
        {
            synchronized ( this )
            {
                if ( consoleLogger == null )
                {
                    consoleLogger = new PluginConsoleLogger( logger );
                }
            }
        }
        return consoleLogger;
    }

    private static <T extends ToolchainManager> Toolchain getToolchainMaven33x( Class<T> toolchainManagerType,
                                                                                T toolchainManager,
                                                                                MavenSession session,
                                                                                Map<String, String> toolchainArgs )
        throws MojoFailureException
    {
        Method getToolchainsMethod =
            tryGetMethod( toolchainManagerType, "getToolchains", MavenSession.class, String.class, Map.class );
        if ( getToolchainsMethod != null )
        {
            //noinspection unchecked
            List<Toolchain> tcs = (List<Toolchain>) invokeMethodWithArray( toolchainManager,
                getToolchainsMethod, session, "jdk", toolchainArgs );
            if ( tcs.isEmpty() )
            {
                throw new MojoFailureException(
                    "Requested toolchain specification did not match any configured toolchain: " + toolchainArgs );
            }
            return tcs.get( 0 );
        }
        return null;
    }

    //TODO remove the part with ToolchainManager lookup once we depend on
    //3.0.9 (have it as prerequisite). Define as regular component field then.
    private Toolchain getToolchain() throws MojoFailureException
    {
        Toolchain tc = null;

        if ( getJdkToolchain() != null )
        {
            tc = getToolchainMaven33x( ToolchainManager.class, getToolchainManager(), getSession(), getJdkToolchain() );
        }

        if ( tc == null )
        {
            tc = getToolchainManager().getToolchainFromBuildContext( "jdk", getSession() );
        }

        return tc;
    }

    private void setupStuff() throws MojoFailureException
    {
        surefireDependencyResolver = new SurefireDependencyResolver( getRepositorySystem(),
                getConsoleLogger(), getLocalRepository(),
                getRemoteRepositories(),
                getProjectRemoteRepositories(),
                getPluginName(), getDependencyResolver(),
                getSession().isOffline() );

        if ( getBooterArtifact() == null )
        {
            throw new RuntimeException( "Unable to locate surefire-booter in the list of plugin artifacts" );
        }

        if ( getToolchainManager() != null )
        {
            toolchain = getToolchain();
        }
    }

    @Nonnull
    private DefaultScanResult scanForTestClasses()
        throws MojoFailureException
    {
        DefaultScanResult scan = scanDirectories();
        DefaultScanResult scanDeps = scanDependencies();
        return scan.append( scanDeps );
    }

    private DefaultScanResult scanDirectories()
        throws MojoFailureException
    {
        DirectoryScanner scanner = new DirectoryScanner( getTestClassesDirectory(), getIncludedAndExcludedTests() );
        return scanner.scan();
    }

    List<Artifact> getProjectTestArtifacts()
    {
        return project.getTestArtifacts();
    }

    DefaultScanResult scanDependencies() throws MojoFailureException
    {
        if ( getDependenciesToScan() == null )
        {
            return null;
        }
        else
        {
            try
            {
                DefaultScanResult result = null;

                List<Artifact> dependenciesToScan =
                        filter( getProjectTestArtifacts(), asList( getDependenciesToScan() ) );

                for ( Artifact artifact : dependenciesToScan )
                {
                    String type = artifact.getType();
                    File out = artifact.getFile();
                    if ( out == null || !out.exists()
                            || !( "jar".equals( type ) || out.isDirectory() || out.getName().endsWith( ".jar" ) ) )
                    {
                        continue;
                    }

                    if ( out.isFile() )
                    {
                        DependencyScanner scanner =
                                new DependencyScanner( singletonList( out ), getIncludedAndExcludedTests() );
                        result = result == null ? scanner.scan() : result.append( scanner.scan() );
                    }
                    else if ( out.isDirectory() )
                    {
                        DirectoryScanner scanner =
                                new DirectoryScanner( out, getIncludedAndExcludedTests() );
                        result = result == null ? scanner.scan() : result.append( scanner.scan() );
                    }
                }

                return result;
            }
            catch ( Exception e )
            {
                throw new MojoFailureException( e.getLocalizedMessage(), e );
            }
        }
    }

    boolean verifyParameters()
        throws MojoFailureException, MojoExecutionException
    {
        setProperties( new SurefireProperties( getProperties() ) );
        if ( isSkipExecution() )
        {
            getConsoleLogger().info( "Tests are skipped." );
            return false;
        }

        String jvmToUse = getJvm();
        if ( toolchain != null )
        {
            getConsoleLogger().info( "Toolchain in maven-" + getPluginName() + "-plugin: " + toolchain );
            if ( jvmToUse != null )
            {
                getConsoleLogger().warning( "Toolchains are ignored, 'jvm' parameter is set to " + jvmToUse );
            }
        }

        if ( !getTestClassesDirectory().exists()
            && ( getDependenciesToScan() == null || getDependenciesToScan().length == 0 ) )
        {
            if ( TRUE.equals( getFailIfNoTests() ) )
            {
                throw new MojoFailureException( "No tests to run!" );
            }
            getConsoleLogger().info( "No tests to run." );
        }
        else
        {
            ensureEnableProcessChecker();
            convertDeprecatedForkMode();
            ensureWorkingDirectoryExists();
            ensureParallelRunningCompatibility();
            ensureThreadCountWithPerThread();
            warnIfUselessUseSystemClassLoaderParameter();
            warnIfDefunctGroupsCombinations();
            warnIfRerunClashes();
            warnIfWrongShutdownValue();
            warnIfNotApplicableSkipAfterFailureCount();
            warnIfIllegalTempDir();
            warnIfForkCountIsZero();
        }
        return true;
    }

    private void warnIfForkCountIsZero()
    {
        if ( "0".equals( getForkCount() ) )
        {
            getConsoleLogger().warning( "The parameter forkCount should likely not be 0, not forking a JVM for tests "
                + "reduce test accuracy, ensure to have a <forkCount> >= 1." );
        }
    }

    private void executeAfterPreconditionsChecked( @Nonnull DefaultScanResult scanResult, @Nonnull Platform platform )
        throws MojoExecutionException, MojoFailureException
    {
        TestClassPath testClasspath = generateTestClasspath();
        List<ProviderInfo> providers = createProviders( testClasspath );
        ResolvePathResultWrapper wrapper = findModuleDescriptor( platform.getJdkExecAttributesForTests().getJdkHome() );

        RunResult current = noTestsRun();

        Exception firstForkException = null;
        for ( ProviderInfo provider : providers )
        {
            try
            {
                current =
                    current.aggregate( executeProvider( provider, scanResult, testClasspath, platform, wrapper ) );
            }
            catch ( SurefireBooterForkException | SurefireExecutionException | TestSetFailedException e )
            {
                if ( firstForkException == null )
                {
                    firstForkException = e;
                }
            }
        }

        if ( firstForkException != null )
        {
            current = failure( current, firstForkException );
        }

        handleSummary( current, firstForkException );
    }

    protected List<ProviderInfo> createProviders( TestClassPath testClasspath )
        throws MojoExecutionException
    {
        Artifact junitDepArtifact = getJunitDepArtifact();
        return new ProviderList( new DynamicProviderInfo( null ),
                              new JUnitPlatformProviderInfo( getJUnit5Artifact(), testClasspath ),
                              new TestNgProviderInfo( getTestNgArtifact() ),
                              new JUnitCoreProviderInfo( getJunitArtifact(), junitDepArtifact ),
                              new JUnit4ProviderInfo( getJunitArtifact(), junitDepArtifact ),
                              new JUnit3ProviderInfo() )
            .resolve();
    }

    private SurefireProperties setupProperties()
    {
        SurefireProperties sysProps = null;
        try
        {
            sysProps = SurefireProperties.loadProperties( getSystemPropertiesFile() );
        }
        catch ( IOException e )
        {
            String msg = "The file '" + getSystemPropertiesFile().getAbsolutePath() + "' can't be read.";
            if ( getConsoleLogger().isDebugEnabled() )
            {
                getConsoleLogger().debug( msg, e );
            }
            else
            {
                getConsoleLogger().warning( msg );
            }
        }

        SurefireProperties result =
            SurefireProperties.calculateEffectiveProperties( getSystemProperties(), getSystemPropertyVariables(),
                                                             getUserProperties(), sysProps );

        result.setProperty( "basedir", getBasedir().getAbsolutePath() );
        result.setProperty( "user.dir", getWorkingDirectory().getAbsolutePath() );
        result.setProperty( "localRepository", getLocalRepository().getBasedir() );
        if ( isForking() )
        {
            for ( Object o : result.propertiesThatCannotBeSetASystemProperties() )
            {
                if ( getArgLine() == null || !getArgLine().contains( "-D" + o + "=" ) )
                {
                    getConsoleLogger().warning( o + " cannot be set as system property, use <argLine>-D"
                                                        + o + "=...</argLine> instead"
                    );
                }
            }
            for ( Object systemPropertyMatchingArgLine : systemPropertiesMatchingArgLine( result ) )
            {
                getConsoleLogger()
                        .warning( "The system property "
                                          + systemPropertyMatchingArgLine
                                          + " is configured twice! "
                                          + "The property appears in <argLine/> and any of <systemPropertyVariables/>, "
                                          + "<systemProperties/> or user property."
                        );
            }
        }
        if ( getConsoleLogger().isDebugEnabled() )
        {
            showToLog( result, getConsoleLogger() );
        }
        return result;
    }

    private Set<Object> systemPropertiesMatchingArgLine( SurefireProperties result )
    {
        Set<Object> intersection = new HashSet<>();
        if ( isNotBlank( getArgLine() ) )
        {
            for ( Object systemProperty : result.getStringKeySet() )
            {
                if ( getArgLine().contains( "-D" + systemProperty + "=" ) )
                {
                    intersection.add( systemProperty );
                }
            }

            Set<Object> ignored = result.propertiesThatCannotBeSetASystemProperties();
            intersection.removeAll( ignored );
        }
        return intersection;
    }

    private void showToLog( SurefireProperties props, ConsoleLogger log )
    {
        for ( Object key : props.getStringKeySet() )
        {
            String value = props.getProperty( (String) key );
            log.debug( "Setting system property [" + key + "]=[" + value + "]" );
        }
    }

    @Nonnull
    private RunResult executeProvider( @Nonnull ProviderInfo provider, @Nonnull DefaultScanResult scanResult,
                                       @Nonnull TestClassPath testClasspathWrapper, @Nonnull Platform platform,
                                       @Nonnull ResolvePathResultWrapper resolvedJavaModularityResult )
        throws MojoExecutionException, MojoFailureException, SurefireExecutionException, SurefireBooterForkException,
        TestSetFailedException
    {
        getConsoleLogger().debug( "Using the provider " + provider.getProviderName() );
        SurefireProperties effectiveProperties = setupProperties();
        ClassLoaderConfiguration classLoaderConfiguration = getClassLoaderConfiguration();
        provider.addProviderProperties();
        RunOrderParameters runOrderParameters =
            new RunOrderParameters( getRunOrder(), getStatisticsFile( getConfigChecksum() ) );

        if ( isNotForking() )
        {
            createCopyAndReplaceForkNumPlaceholder( effectiveProperties, 1 ).copyToSystemProperties();

            InPluginVMSurefireStarter surefireStarter = createInprocessStarter( provider, classLoaderConfiguration,
                    runOrderParameters, scanResult, platform, testClasspathWrapper );
            return surefireStarter.runSuitesInProcess( scanResult );
        }
        else
        {
            ForkConfiguration forkConfiguration = createForkConfiguration( platform, resolvedJavaModularityResult );
            if ( getConsoleLogger().isDebugEnabled() )
            {
                showMap( getEnvironmentVariables(), "environment variable" );
                showArray( getExcludedEnvironmentVariables(), "excluded environment variable" );
            }

            Properties originalSystemProperties = (Properties) System.getProperties().clone();
            ForkStarter forkStarter = null;
            try
            {
                forkStarter = createForkStarter( provider, forkConfiguration, classLoaderConfiguration,
                                                       runOrderParameters, getConsoleLogger(), scanResult,
                                                       testClasspathWrapper, platform, resolvedJavaModularityResult );

                return forkStarter.run( effectiveProperties, scanResult );
            }
            catch ( SurefireBooterForkException e )
            {
                forkStarter.killOrphanForks();
                throw e;
            }
            finally
            {
                System.setProperties( originalSystemProperties );
                cleanupForkConfiguration( forkConfiguration );
            }
        }
    }

    public static SurefireProperties createCopyAndReplaceForkNumPlaceholder(
        SurefireProperties effectiveSystemProperties, int threadNumber )
    {
        SurefireProperties filteredProperties = new SurefireProperties( ( KeyValueSource) effectiveSystemProperties );
        for ( Entry<Object, Object> entry : effectiveSystemProperties.entrySet() )
        {
            if ( entry.getValue() instanceof String )
            {
                String value = (String) entry.getValue();
                filteredProperties.put( entry.getKey(), replaceThreadNumberPlaceholders( value, threadNumber ) );
            }
        }
        return filteredProperties;
    }

    protected void cleanupForkConfiguration( ForkConfiguration forkConfiguration )
    {
        if ( !getConsoleLogger().isDebugEnabled() && forkConfiguration != null )
        {
            File tempDirectory = forkConfiguration.getTempDirectory();
            try
            {
                FileUtils.deleteDirectory( tempDirectory );
            }
            catch ( IOException e )
            {
                getConsoleLogger()
                        .warning( "Could not delete temp directory " + tempDirectory + " because " + e.getMessage() );
            }
        }
    }

    protected void logReportsDirectory()
    {
        logDebugOrCliShowErrors(
            capitalizeFirstLetter( getPluginName() ) + " report directory: " + getReportsDirectory() );
    }

    public RepositorySystem getRepositorySystem()
    {
        return repositorySystem;
    }

    public void setRepositorySystem( RepositorySystem repositorySystem )
    {
        this.repositorySystem = repositorySystem;
    }

    public DependencyResolver getDependencyResolver()
    {
        return dependencyResolver;
    }

    public void setDependencyResolver( DependencyResolver dependencyResolver )
    {
        this.dependencyResolver = dependencyResolver;
    }

    private boolean existsModuleDescriptor( ResolvePathResultWrapper resolvedJavaModularityResult )
    {
        return resolvedJavaModularityResult.getResolvePathResult() != null;
    }

    private ResolvePathResultWrapper findModuleDescriptor( File jdkHome )
    {
        File mainBuildPath = getMainBuildPath();

        if ( mainBuildPath.isDirectory() && !new File( mainBuildPath, "module-info.class" ).exists() )
        {
            return new ResolvePathResultWrapper( null, true );
        }

        try
        {
            ResolvePathRequest<?> request = ResolvePathRequest.ofFile( mainBuildPath ).setJdkHome( jdkHome );
            ResolvePathResult result = getLocationManager().resolvePath( request );
            return new ResolvePathResultWrapper( result.getModuleNameSource() == null ? null : result, true );
        }
        catch ( Exception e )
        {
            return new ResolvePathResultWrapper( null, true );
        }
    }

    private boolean canExecuteProviderWithModularPath( Platform platform,
                                                       ResolvePathResultWrapper resolvedJavaModularityResult )
    {
        return useModulePath()
                && platform.getJdkExecAttributesForTests().isJava9AtLeast()
                && existsModuleDescriptor( resolvedJavaModularityResult );
    }

    /**
     * Converts old TestNG configuration parameters over to new properties based configuration
     * method. (if any are defined the old way)
     */
    private void convertTestNGParameters() throws MojoExecutionException
    {
        if ( this.getParallel() != null )
        {
            getProperties().setProperty( ProviderParameterNames.PARALLEL_PROP, this.getParallel() );
        }
        convertGroupParameters();

        if ( this.getThreadCount() > 0 )
        {
            getProperties().setProperty( ProviderParameterNames.THREADCOUNT_PROP,
                                         Integer.toString( this.getThreadCount() ) );
        }
        if ( this.getObjectFactory() != null )
        {
            getProperties().setProperty( "objectfactory", this.getObjectFactory() );
        }
        if ( this.getTestClassesDirectory() != null )
        {
            getProperties().setProperty( "testng.test.classpath", getTestClassesDirectory().getAbsolutePath() );
        }

        Artifact testNgArtifact = getTestNgArtifact();
        if ( testNgArtifact != null )
        {
            DefaultArtifactVersion defaultArtifactVersion = new DefaultArtifactVersion( testNgArtifact.getVersion() );
            getProperties().setProperty( "testng.configurator", getConfiguratorName( defaultArtifactVersion,
                                                                                           getConsoleLogger()
                    )
            );
        }
    }

    private static String getConfiguratorName( ArtifactVersion version, PluginConsoleLogger log )
        throws MojoExecutionException
    {
        try
        {
            VersionRange range = VersionRange.createFromVersionSpec( "[4.7,5.2)" );
            if ( range.containsVersion( version ) )
            {
                return "org.apache.maven.surefire.testng.conf.TestNG4751Configurator";
            }
            range = VersionRange.createFromVersionSpec( "[5.2,5.3)" );
            if ( range.containsVersion( version ) )
            {
                return "org.apache.maven.surefire.testng.conf.TestNG52Configurator";
            }
            range = VersionRange.createFromVersionSpec( "[5.3,5.10)" );
            if ( range.containsVersion( version ) )
            {
                return "org.apache.maven.surefire.testng.conf.TestNGMapConfigurator";
            }
            range = VersionRange.createFromVersionSpec( "[5.10,5.13)" );
            if ( range.containsVersion( version ) )
            {
                return "org.apache.maven.surefire.testng.conf.TestNG510Configurator";
            }
            range = VersionRange.createFromVersionSpec( "[5.13,5.14.1)" );
            if ( range.containsVersion( version ) )
            {
                return "org.apache.maven.surefire.testng.conf.TestNG513Configurator";
            }
            range = VersionRange.createFromVersionSpec( "[5.14.1,5.14.3)" );
            if ( range.containsVersion( version ) )
            {
                log.warning( "The 'reporter' or 'listener' may not work properly in TestNG 5.14.1 and 5.14.2." );
                return "org.apache.maven.surefire.testng.conf.TestNG5141Configurator";
            }
            range = VersionRange.createFromVersionSpec( "[5.14.3,6.0)" );
            if ( range.containsVersion( version ) )
            {
                if ( version.equals( new DefaultArtifactVersion( "[5.14.3,5.14.5]" ) ) )
                {
                    throw new MojoExecutionException( "TestNG 5.14.3-5.14.5 is not supported. "
                            + "System dependency org.testng:guice missed path." );
                }
                return "org.apache.maven.surefire.testng.conf.TestNG5143Configurator";
            }
            range = VersionRange.createFromVersionSpec( "[6.0,)" );
            if ( range.containsVersion( version ) )
            {
                return "org.apache.maven.surefire.testng.conf.TestNG60Configurator";
            }

            throw new MojoExecutionException( "Unknown TestNG version " + version );
        }
        catch ( InvalidVersionSpecificationException invsex )
        {
            throw new MojoExecutionException( "Bug in plugin. Please report it with the attached stacktrace", invsex );
        }
    }


    private void convertGroupParameters()
    {
        if ( this.getExcludedGroups() != null )
        {
            getProperties().setProperty( ProviderParameterNames.TESTNG_EXCLUDEDGROUPS_PROP, this.getExcludedGroups() );
        }
        if ( this.getGroups() != null )
        {
            getProperties().setProperty( ProviderParameterNames.TESTNG_GROUPS_PROP, this.getGroups() );
        }
    }

    protected boolean isAnyConcurrencySelected()
    {
        return getParallel() != null && !getParallel().trim().isEmpty();
    }

    protected boolean isAnyGroupsSelected()
    {
        return this.getGroups() != null || this.getExcludedGroups() != null;
    }

    /**
     * Converts old JUnit configuration parameters over to new properties based configuration
     * method. (if any are defined the old way)
     */
    private void convertJunitCoreParameters() throws MojoExecutionException
    {
        checkThreadCountEntity( getThreadCountSuites(), "suites" );
        checkThreadCountEntity( getThreadCountClasses(), "classes" );
        checkThreadCountEntity( getThreadCountMethods(), "methods" );

        String usedParallel = ( getParallel() != null ) ? getParallel() : "none";

        if ( !"none".equals( usedParallel ) )
        {
            checkNonForkedThreads( parallel );
        }

        getProperties().setProperty( ProviderParameterNames.PARALLEL_PROP, usedParallel );
        getProperties().setProperty( ProviderParameterNames.THREADCOUNT_PROP, Integer.toString( getThreadCount() ) );
        getProperties().setProperty( "perCoreThreadCount", Boolean.toString( getPerCoreThreadCount() ) );
        getProperties().setProperty( "useUnlimitedThreads", Boolean.toString( getUseUnlimitedThreads() ) );
        getProperties().setProperty( ProviderParameterNames.THREADCOUNTSUITES_PROP,
                                     Integer.toString( getThreadCountSuites() ) );
        getProperties().setProperty( ProviderParameterNames.THREADCOUNTCLASSES_PROP,
                                     Integer.toString( getThreadCountClasses() ) );
        getProperties().setProperty( ProviderParameterNames.THREADCOUNTMETHODS_PROP,
                                     Integer.toString( getThreadCountMethods() ) );
        getProperties().setProperty( ProviderParameterNames.PARALLEL_TIMEOUT_PROP,
                                     Double.toString( getParallelTestsTimeoutInSeconds() ) );
        getProperties().setProperty( ProviderParameterNames.PARALLEL_TIMEOUTFORCED_PROP,
                                     Double.toString( getParallelTestsTimeoutForcedInSeconds() ) );
        getProperties().setProperty( ProviderParameterNames.PARALLEL_OPTIMIZE_PROP,
                                     Boolean.toString( isParallelOptimized() ) );

        String message = "parallel='" + usedParallel + '\''
            + ", perCoreThreadCount=" + getPerCoreThreadCount()
            + ", threadCount=" + getThreadCount()
            + ", useUnlimitedThreads=" + getUseUnlimitedThreads()
            + ", threadCountSuites=" + getThreadCountSuites()
            + ", threadCountClasses=" + getThreadCountClasses()
            + ", threadCountMethods=" + getThreadCountMethods()
            + ", parallelOptimized=" + isParallelOptimized();

        logDebugOrCliShowErrors( message );
    }

    private void checkNonForkedThreads( String parallel ) throws MojoExecutionException
    {
        if ( "suites".equals( parallel ) )
        {
            if ( !( getUseUnlimitedThreads() || getThreadCount() > 0 ^ getThreadCountSuites() > 0 ) )
            {
                throw new MojoExecutionException(
                        "Use threadCount or threadCountSuites > 0 or useUnlimitedThreads=true for parallel='suites'" );
            }
            setThreadCountClasses( 0 );
            setThreadCountMethods( 0 );
        }
        else if ( "classes".equals( parallel ) )
        {
            if ( !( getUseUnlimitedThreads() || getThreadCount() > 0 ^ getThreadCountClasses() > 0 ) )
            {
                throw new MojoExecutionException(
                        "Use threadCount or threadCountClasses > 0 or useUnlimitedThreads=true for parallel='classes'"
                      );
            }
            setThreadCountSuites( 0 );
            setThreadCountMethods( 0 );
        }
        else if ( "methods".equals( parallel ) )
        {
            if ( !( getUseUnlimitedThreads() || getThreadCount() > 0 ^ getThreadCountMethods() > 0 ) )
            {
                throw new MojoExecutionException(
                        "Use threadCount or threadCountMethods > 0 or useUnlimitedThreads=true for parallel='methods'"
                      );
            }
            setThreadCountSuites( 0 );
            setThreadCountClasses( 0 );
        }
        else if ( "suitesAndClasses".equals( parallel ) )
        {
            if ( !( getUseUnlimitedThreads()
                    || onlyThreadCount()
                    || getThreadCountSuites() > 0 && getThreadCountClasses() > 0
                        && getThreadCount() == 0 && getThreadCountMethods() == 0
                    || getThreadCount() > 0 && getThreadCountSuites() > 0 && getThreadCountClasses() > 0
                        && getThreadCountMethods() == 0
                    || getThreadCount() > 0 && getThreadCountSuites() > 0 && getThreadCount() > getThreadCountSuites()
                        && getThreadCountClasses() == 0 && getThreadCountMethods() == 0 ) )
            {
                throw new MojoExecutionException( "Use useUnlimitedThreads=true, "
                        + "or only threadCount > 0, "
                        + "or (threadCountSuites > 0 and threadCountClasses > 0), "
                        + "or (threadCount > 0 and threadCountSuites > 0 and threadCountClasses > 0) "
                        + "or (threadCount > 0 and threadCountSuites > 0 and threadCount > threadCountSuites) "
                        + "for parallel='suitesAndClasses' or 'both'" );
            }
            setThreadCountMethods( 0 );
        }
        else if ( "suitesAndMethods".equals( parallel ) )
        {
            if ( !( getUseUnlimitedThreads()
                    || onlyThreadCount()
                    || getThreadCountSuites() > 0 && getThreadCountMethods() > 0
                        && getThreadCount() == 0 && getThreadCountClasses() == 0
                    || getThreadCount() > 0 && getThreadCountSuites() > 0 && getThreadCountMethods() > 0
                        && getThreadCountClasses() == 0
                    || getThreadCount() > 0 && getThreadCountSuites() > 0 && getThreadCount() > getThreadCountSuites()
                        && getThreadCountClasses() == 0 && getThreadCountMethods() == 0 ) )
            {
                throw new MojoExecutionException( "Use useUnlimitedThreads=true, "
                        + "or only threadCount > 0, "
                        + "or (threadCountSuites > 0 and threadCountMethods > 0), "
                        + "or (threadCount > 0 and threadCountSuites > 0 and threadCountMethods > 0), "
                        + "or (threadCount > 0 and threadCountSuites > 0 and threadCount > threadCountSuites) "
                        + "for parallel='suitesAndMethods'" );
            }
            setThreadCountClasses( 0 );
        }
        else if ( "both".equals( parallel ) || "classesAndMethods".equals( parallel ) )
        {
            if ( !( getUseUnlimitedThreads()
                    || onlyThreadCount()
                    || getThreadCountClasses() > 0 && getThreadCountMethods() > 0
                        && getThreadCount() == 0 && getThreadCountSuites() == 0
                    || getThreadCount() > 0 && getThreadCountClasses() > 0 && getThreadCountMethods() > 0
                        && getThreadCountSuites() == 0
                    || getThreadCount() > 0 && getThreadCountClasses() > 0 && getThreadCount() > getThreadCountClasses()
                        && getThreadCountSuites() == 0 && getThreadCountMethods() == 0 ) )
            {
                throw new MojoExecutionException( "Use useUnlimitedThreads=true, "
                        + "or only threadCount > 0, "
                        + "or (threadCountClasses > 0 and threadCountMethods > 0), "
                        + "or (threadCount > 0 and threadCountClasses > 0 and threadCountMethods > 0), "
                        + "or (threadCount > 0 and threadCountClasses > 0 and threadCount > threadCountClasses) "
                        + "for parallel='both' or parallel='classesAndMethods'" );
            }
            setThreadCountSuites( 0 );
        }
        else if ( "all".equals( parallel ) )
        {
            if ( !( getUseUnlimitedThreads()
                    || onlyThreadCount()
                    || getThreadCountSuites() > 0 && getThreadCountClasses() > 0 && getThreadCountMethods() > 0
                    || getThreadCount() > 0 && getThreadCountSuites() > 0 && getThreadCountClasses() > 0
                        && getThreadCountMethods() == 0
                        && getThreadCount() > ( getThreadCountSuites() + getThreadCountClasses() ) ) )
            {
                throw new MojoExecutionException( "Use useUnlimitedThreads=true, "
                        + "or only threadCount > 0, "
                        + "or (threadCountSuites > 0 and threadCountClasses > 0 and threadCountMethods > 0), "
                        + "or every thread-count is specified, "
                        + "or (threadCount > 0 and threadCountSuites > 0 and threadCountClasses > 0 "
                        + "and threadCount > threadCountSuites + threadCountClasses) "
                        + "for parallel='all'" );
            }
        }
        else
        {
            throw new MojoExecutionException( "Illegal parallel='" + parallel + "'" );
        }
    }

    private boolean onlyThreadCount()
    {
        return getThreadCount() > 0 && getThreadCountSuites() == 0 && getThreadCountClasses() == 0
                && getThreadCountMethods() == 0;
    }

    private static void checkThreadCountEntity( int count, String entity )
        throws MojoExecutionException
    {
        if ( count < 0 )
        {
            throw new MojoExecutionException(
                    "parallel maven execution does not allow negative thread-count" + entity );
        }
    }

    private boolean isJunit47Compatible( Artifact artifact )
    {
        return isWithinVersionSpec( artifact, "[4.7,)" );
    }

    private boolean isAnyJunit4( Artifact artifact )
    {
        return isWithinVersionSpec( artifact, "[4.0,)" );
    }

    private static boolean isForkModeNever( String forkMode )
    {
        return FORK_NEVER.equals( forkMode );
    }

    protected boolean isForking()
    {
        return 0 < getEffectiveForkCount();
    }

    String getEffectiveForkMode()
    {
        String forkMode1 = getForkMode();

        if ( toolchain != null && isForkModeNever( forkMode1 ) )
        {
            return FORK_ONCE;
        }

        return getEffectiveForkMode( forkMode1 );
    }

    private List<RunOrder> getRunOrders()
    {
        String runOrderString = getRunOrder();
        RunOrder[] runOrder = runOrderString == null ? RunOrder.DEFAULT : RunOrder.valueOfMulti( runOrderString );
        return asList( runOrder );
    }

    private boolean requiresRunHistory()
    {
        final List<RunOrder> runOrders = getRunOrders();
        return runOrders.contains( RunOrder.BALANCED ) || runOrders.contains( RunOrder.FAILEDFIRST );
    }

    private boolean getEffectiveFailIfNoTests()
    {
        if ( isSpecificTestSpecified() )
        {
            if ( getFailIfNoSpecifiedTests() != null )
            {
                return getFailIfNoSpecifiedTests();
            }
            else if ( getFailIfNoTests() != null )
            {
                return getFailIfNoTests();
            }
            else
            {
                return true;
            }
        }
        else
        {
            return getFailIfNoTests() != null && getFailIfNoTests();
        }
    }

    private ProviderConfiguration createProviderConfiguration( RunOrderParameters runOrderParameters )
        throws MojoExecutionException, MojoFailureException
    {
        final ReporterConfiguration reporterConfiguration =
            new ReporterConfiguration( getReportsDirectory(), isTrimStackTrace() );

        final Artifact testNgArtifact = getTestNgArtifact();
        final boolean isTestNg = testNgArtifact != null;
        final TestArtifactInfo testNg =
            isTestNg ? new TestArtifactInfo( testNgArtifact.getVersion(), testNgArtifact.getClassifier() ) : null;
        final TestRequest testSuiteDefinition = new TestRequest( suiteXmlFiles(),
                                                                 getTestSourceDirectory(),
                                                                 getSpecificTests(),
                                                                 getRerunFailingTestsCount() );

        final boolean actualFailIfNoTests;
        DirectoryScannerParameters directoryScannerParameters = null;
        if ( hasSuiteXmlFiles() && !isSpecificTestSpecified() )
        {
            actualFailIfNoTests = getFailIfNoTests() != null && getFailIfNoTests();
            if ( !isTestNg )
            {
                throw new MojoExecutionException( "suiteXmlFiles is configured, but there is no TestNG dependency" );
            }
        }
        else
        {
            if ( isSpecificTestSpecified() )
            {
                actualFailIfNoTests = getEffectiveFailIfNoTests();
                setFailIfNoTests( actualFailIfNoTests );
            }
            else
            {
                actualFailIfNoTests = getFailIfNoTests() != null && getFailIfNoTests();
            }

            // @todo remove these three params and use DirectoryScannerParameters to pass into DirectoryScanner only
            // @todo or remove it in next major version :: 3.0
            // @todo remove deprecated methods in ProviderParameters => included|excluded|specificTests not needed here

            List<String> actualIncludes = getIncludeList(); // Collections.emptyList(); behaves same
            List<String> actualExcludes = getExcludeList(); // Collections.emptyList(); behaves same
            // Collections.emptyList(); behaves same
            List<String> specificTests = Collections.emptyList();

            directoryScannerParameters =
                new DirectoryScannerParameters( getTestClassesDirectory(), actualIncludes, actualExcludes,
                                                specificTests, actualFailIfNoTests, getRunOrder() );
        }

        Map<String, String> providerProperties = toStringProperties( getProperties() );

        return new ProviderConfiguration( directoryScannerParameters, runOrderParameters, actualFailIfNoTests,
                                          reporterConfiguration,
                                          testNg, // Not really used in provider. Limited to de/serializer.
                                          testSuiteDefinition, providerProperties, null,
                                          false, cli, getSkipAfterFailureCount(),
                                          Shutdown.parameterOf( getShutdown() ),
                                          getForkedProcessExitTimeoutInSeconds() );
    }

    private static Map<String, String> toStringProperties( Properties properties )
    {
        Map<String, String> h = new ConcurrentHashMap<>( properties.size() );
        for ( Enumeration<?> e = properties.keys() ; e.hasMoreElements() ; )
        {
            Object k = e.nextElement();
            Object v = properties.get( k );
            if ( k.getClass() == String.class && v.getClass() == String.class )
            {
                h.put( (String) k, (String) v );
            }
        }
        return h;
    }

    private File getStatisticsFile( String configurationHash )
    {
        return new File( getBasedir(), ".surefire-" + configurationHash );
    }

    private StartupConfiguration createStartupConfiguration( @Nonnull ProviderInfo provider, boolean isForking,
                                                             @Nonnull ClassLoaderConfiguration classLoaderConfiguration,
                                                             @Nonnull DefaultScanResult scanResult,
                                                             @Nonnull TestClassPath testClasspathWrapper,
                                                             @Nonnull Platform platform,
                                                             @Nonnull ResolvePathResultWrapper resolvedJavaModularity )
        throws MojoExecutionException
    {
        try
        {
            Set<Artifact> providerArtifacts = provider.getProviderClasspath();
            String providerName = provider.getProviderName();
            if ( isForking && canExecuteProviderWithModularPath( platform, resolvedJavaModularity ) )
            {
                File jdkHome = platform.getJdkExecAttributesForTests().getJdkHome();
                return newStartupConfigWithModularPath( classLoaderConfiguration, providerArtifacts, providerName,
                    resolvedJavaModularity, scanResult, jdkHome.getAbsolutePath(), testClasspathWrapper );
            }
            else
            {
                return newStartupConfigWithClasspath( classLoaderConfiguration, providerArtifacts, providerName,
                        testClasspathWrapper );
            }
        }
        catch ( IOException e )
        {
            throw new MojoExecutionException( e.getMessage(), e );
        }
    }

    private StartupConfiguration newStartupConfigWithClasspath(
            @Nonnull ClassLoaderConfiguration classLoaderConfiguration, @Nonnull Set<Artifact> providerArtifacts,
            @Nonnull String providerName, @Nonnull TestClassPath testClasspathWrapper )
    {
        Classpath testClasspath = testClasspathWrapper.toClasspath();

        Classpath providerClasspath = classpathCache.getCachedClassPath( providerName );
        if ( providerClasspath == null )
        {
            providerClasspath = classpathCache.setCachedClasspath( providerName, providerArtifacts );
        }

        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:" ) );

        Artifact[] additionalInProcArtifacts = { getCommonArtifact(), getBooterArtifact(), getExtensionsArtifact(),
            getApiArtifact(), getSpiArtifact(), getLoggerApiArtifact(), getSurefireSharedUtilsArtifact() };
        Set<Artifact> inProcArtifacts = retainInProcArtifactsUnique( providerArtifacts, additionalInProcArtifacts );
        Classpath inProcClasspath = createInProcClasspath( providerClasspath, inProcArtifacts );
        getConsoleLogger().debug( inProcClasspath.getLogMessage( "in-process classpath:" ) );
        getConsoleLogger().debug( inProcClasspath.getCompactLogMessage( "in-process(compact) classpath:" ) );

        ClasspathConfiguration classpathConfiguration = new ClasspathConfiguration( testClasspath, providerClasspath,
                inProcClasspath, effectiveIsEnableAssertions(), isChildDelegation() );

        return new StartupConfiguration( providerName, classpathConfiguration, classLoaderConfiguration,
            ProcessCheckerType.toEnum( getEnableProcessChecker() ) );
    }

    private static Set<Artifact> retainInProcArtifactsUnique( Set<Artifact> providerArtifacts,
                                                         Artifact... inPluginArtifacts )
    {
        Set<Artifact> result = new LinkedHashSet<>();
        for ( Artifact inPluginArtifact : inPluginArtifacts )
        {
            boolean contains = false;
            for ( Artifact providerArtifact : providerArtifacts )
            {
                if ( hasGroupArtifactId( providerArtifact.getGroupId(), providerArtifact.getArtifactId(),
                        inPluginArtifact ) )
                {
                    contains = true;
                    break;
                }
            }
            if ( !contains )
            {
                result.add( inPluginArtifact );
            }
        }
        return result;
    }

    private static boolean hasGroupArtifactId( String groupId, String artifactId, Artifact artifact )
    {
        return groupId.equals( artifact.getGroupId() ) && artifactId.equals( artifact.getArtifactId() );
    }

    private static Classpath createInProcClasspath( Classpath providerClasspath, Set<Artifact> newArtifacts )
    {
        Classpath inprocClasspath = providerClasspath.clone();
        for ( Artifact newArtifact : newArtifacts )
        {
            inprocClasspath = inprocClasspath.addClassPathElementUrl( newArtifact.getFile().getAbsolutePath() );
        }
        return inprocClasspath;
    }

    /**
     * For testing purposes - Mockito.
     * @return plexus component
     */
    private LocationManager getLocationManager()
    {
        return locationManager;
    }

    private StartupConfiguration newStartupConfigWithModularPath(
        @Nonnull ClassLoaderConfiguration classLoaderConfiguration, @Nonnull Set<Artifact> providerArtifacts,
        @Nonnull String providerName, @Nonnull ResolvePathResultWrapper moduleDescriptor,
        @Nonnull DefaultScanResult scanResult, @Nonnull String javaHome, @Nonnull TestClassPath testClasspathWrapper )
            throws IOException
    {
        Classpath testClasspath = testClasspathWrapper.toClasspath();

        Classpath providerClasspath = classpathCache.getCachedClassPath( providerName );
        if ( providerClasspath == null )
        {
            providerClasspath = classpathCache.setCachedClasspath( providerName, providerArtifacts );
        }

        ResolvePathsRequest<String> req = ResolvePathsRequest.ofStrings( testClasspath.getClassPath() )
                .setJdkHome( javaHome )
                .setModuleDescriptor( moduleDescriptor.getResolvePathResult().getModuleDescriptor() );

        ResolvePathsResult<String> result = getLocationManager().resolvePaths( req );
        for ( Entry<String, Exception> entry : result.getPathExceptions().entrySet() )
        {
            // Probably JDK version < 9. Other known causes: passing a non-jar or a corrupted jar.
            getConsoleLogger()
                    .warning( "Exception for '" + entry.getKey() + "'.", entry.getValue() );
        }

        testClasspath = new Classpath( result.getClasspathElements() );
        Classpath testModulepath = new Classpath( result.getModulepathElements().keySet() );

        SortedSet<String> packages = new TreeSet<>();

        for ( String className : scanResult.getClasses() )
        {
            packages.add( substringBeforeLast( className, "." ) );
        }

        getConsoleLogger().debug( "main module descriptor name: " + result.getMainModuleDescriptor().name() );

        ModularClasspath modularClasspath = new ModularClasspath( result.getMainModuleDescriptor().name(),
                testModulepath.getClassPath(), packages, getTestClassesDirectory() );

        Artifact[] additionalInProcArtifacts = { getCommonArtifact(), getBooterArtifact(), getExtensionsArtifact(),
            getApiArtifact(), getSpiArtifact(), getLoggerApiArtifact(), getSurefireSharedUtilsArtifact() };
        Set<Artifact> inProcArtifacts = retainInProcArtifactsUnique( providerArtifacts, additionalInProcArtifacts );
        Classpath inProcClasspath = createInProcClasspath( providerClasspath, inProcArtifacts );

        ModularClasspathConfiguration classpathConfiguration = new ModularClasspathConfiguration( modularClasspath,
                testClasspath, providerClasspath, inProcClasspath, 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:" ) );
        getConsoleLogger().debug( inProcClasspath.getLogMessage( "in-process classpath:" ) );
        getConsoleLogger().debug( inProcClasspath.getCompactLogMessage( "in-process(compact) classpath:" ) );

        return new StartupConfiguration( providerName, classpathConfiguration, classLoaderConfiguration,
            ProcessCheckerType.toEnum( getEnableProcessChecker() ) );
    }

    private Artifact getCommonArtifact()
    {
        return getPluginArtifactMap().get( "org.apache.maven.surefire:maven-surefire-common" );
    }

    private Artifact getExtensionsArtifact()
    {
        return getPluginArtifactMap().get( "org.apache.maven.surefire:surefire-extensions-api" );
    }

    private Artifact getSpiArtifact()
    {
        return getPluginArtifactMap().get( "org.apache.maven.surefire:surefire-extensions-spi" );
    }

    private Artifact getApiArtifact()
    {
        return getPluginArtifactMap().get( "org.apache.maven.surefire:surefire-api" );
    }

    private Artifact getSurefireSharedUtilsArtifact()
    {
        return getPluginArtifactMap().get( "org.apache.maven.surefire:surefire-shared-utils" );
    }

    private Artifact getLoggerApiArtifact()
    {
        return getPluginArtifactMap().get( "org.apache.maven.surefire:surefire-logger-api" );
    }

    private Artifact getBooterArtifact()
    {
        return getPluginArtifactMap().get( "org.apache.maven.surefire:surefire-booter" );
    }

    private Artifact getShadefireArtifact()
    {
        return getPluginArtifactMap().get( "org.apache.maven.surefire:surefire-shadefire" );
    }

    private StartupReportConfiguration getStartupReportConfiguration( String configChecksum, boolean isForkMode )
    {
        SurefireStatelessReporter xmlReporter =
                statelessTestsetReporter == null
                        ? new SurefireStatelessReporter( /*todo call def. constr.*/ isDisableXmlReport(), "3.0" )
                        : statelessTestsetReporter;

        xmlReporter.setDisable( isDisableXmlReport() ); // todo change to Boolean in the version 3.0.0-M6

        SurefireConsoleOutputReporter outReporter =
                consoleOutputReporter == null ? new SurefireConsoleOutputReporter() : consoleOutputReporter;

        SurefireStatelessTestsetInfoReporter testsetReporter =
                statelessTestsetInfoReporter == null
                        ? new SurefireStatelessTestsetInfoReporter() : statelessTestsetInfoReporter;

        return new StartupReportConfiguration( isUseFile(), isPrintSummary(), getReportFormat(),
                                               isRedirectTestOutputToFile(),
                                               getReportsDirectory(), isTrimStackTrace(), getReportNameSuffix(),
                                               getStatisticsFile( configChecksum ), requiresRunHistory(),
                                               getRerunFailingTestsCount(), getReportSchemaLocation(), getEncoding(),
                                               isForkMode, xmlReporter, outReporter, testsetReporter );
    }

    private boolean isSpecificTestSpecified()
    {
        return isNotBlank( getTest() );
    }

    @Nonnull private List<String> readListFromFile( @Nonnull final File file )
    {
        getConsoleLogger().debug( "Reading list from: " + file );

        if ( !file.exists() )
        {
            throw new RuntimeException( "Failed to load list from file: " + file );
        }

        try
        {
            List<String> list = FileUtils.loadFile( file );

            if ( getConsoleLogger().isDebugEnabled() )
            {
                getConsoleLogger().debug( "List contents:" );
                for ( String entry : list )
                {
                    getConsoleLogger().debug( "  " + entry );
                }
            }
            return list;
        }
        catch ( IOException e )
        {
            throw new RuntimeException( "Failed to load list from file: " + file, e );
        }
    }

    private void maybeAppendList( List<String> base, List<String> list )
    {
        if ( list != null )
        {
            base.addAll( list );
        }
    }

    @Nonnull private List<String> getExcludeList()
        throws MojoFailureException
    {
        List<String> actualExcludes = null;
        if ( isSpecificTestSpecified() )
        {
            actualExcludes = Collections.emptyList();
        }
        else
        {
            if ( getExcludesFile() != null )
            {
                actualExcludes = readListFromFile( getExcludesFile() );
            }

            if ( actualExcludes == null )
            {
                actualExcludes = getExcludes();
            }
            else
            {
                maybeAppendList( actualExcludes, getExcludes() );
            }

            checkMethodFilterInIncludesExcludes( actualExcludes );

            if ( actualExcludes == null || actualExcludes.isEmpty() )
            {
                actualExcludes = Collections.singletonList( getDefaultExcludes() );
            }
        }
        return filterNulls( actualExcludes );
    }

    private List<String> getIncludeList()
        throws MojoFailureException
    {
        List<String> includes = null;
        if ( isSpecificTestSpecified() )
        {
            includes = new ArrayList<>();
            addAll( includes, split( getTest(), "," ) );
        }
        else
        {
            if ( getIncludesFile() != null )
            {
                includes = readListFromFile( getIncludesFile() );
            }

            if ( includes == null )
            {
                includes = getIncludes();
            }
            else
            {
                maybeAppendList( includes, getIncludes() );
            }

            checkMethodFilterInIncludesExcludes( includes );

            if ( includes == null || includes.isEmpty() )
            {
                includes = asList( getDefaultIncludes() );
            }
        }

        return filterNulls( includes );
    }

    private void checkMethodFilterInIncludesExcludes( Iterable<String> patterns )
        throws MojoFailureException
    {
        if ( patterns != null )
        {
            for ( String pattern : patterns )
            {
                if ( pattern != null && pattern.contains( "#" ) )
                {
                    throw new MojoFailureException( "Method filter prohibited in "
                                                        + "includes|excludes|includesFile|excludesFile parameter: "
                                                        + pattern );
                }
            }
        }
    }

    private TestListResolver getIncludedAndExcludedTests()
        throws MojoFailureException
    {
        if ( includedExcludedTests == null )
        {
            includedExcludedTests = new TestListResolver( getIncludeList(), getExcludeList() );
        }
        return includedExcludedTests;
    }

    public TestListResolver getSpecificTests()
    {
        if ( specificTests == null )
        {
            specificTests = new TestListResolver( getTest() );
        }
        return specificTests;
    }

    @Nonnull private List<String> filterNulls( @Nonnull List<String> toFilter )
    {
        List<String> result = new ArrayList<>( toFilter.size() );
        for ( String item : toFilter )
        {
            if ( item != null )
            {
                item = item.trim();
                if ( !item.isEmpty() )
                {
                    result.add( item );
                }
            }
        }

        return result;
    }

    private Artifact getTestNgArtifact()
        throws MojoExecutionException
    {
        Artifact artifact = getProjectArtifactMap().get( getTestNGArtifactName() );
        Artifact projectArtifact = project.getArtifact();
        String projectArtifactName = projectArtifact.getGroupId() + ":" + projectArtifact.getArtifactId();

        if ( artifact != null )
        {
            VersionRange range = createVersionRange();
            if ( !range.containsVersion( new DefaultArtifactVersion( artifact.getVersion() ) ) )
            {
                throw new MojoExecutionException(
                    "TestNG support requires version 4.7 or above. You have declared version "
                        + artifact.getVersion() );
            }
        }
        else if ( projectArtifactName.equals( getTestNGArtifactName() ) )
        {
            artifact = projectArtifact;
        }

        return artifact;

    }

    private VersionRange createVersionRange()
    {
        try
        {
            return VersionRange.createFromVersionSpec( "[4.7,)" );
        }
        catch ( InvalidVersionSpecificationException e )
        {
            throw new RuntimeException( e );
        }
    }

    private Artifact getJunitArtifact()
    {
        Artifact artifact = getProjectArtifactMap().get( getJunitArtifactName() );
        Artifact projectArtifact = project.getArtifact();
        String projectArtifactName = projectArtifact.getGroupId() + ":" + projectArtifact.getArtifactId();

        if ( artifact == null && projectArtifactName.equals( getJunitArtifactName() ) )
        {
            artifact = projectArtifact;
        }

        return artifact;
    }

    private Artifact getJunitDepArtifact()
    {
        return getProjectArtifactMap().get( "junit:junit-dep" );
    }

    private Artifact getJUnit5Artifact()
    {
        if ( getProjectArtifactMap().get( "org.junit.platform:junit-platform-runner" ) != null )
        {
            return null;
        }

        Artifact artifact = getPluginArtifactMap().get( "org.junit.platform:junit-platform-engine" );
        if ( artifact == null )
        {
            return getProjectArtifactMap().get( "org.junit.platform:junit-platform-commons" );
        }

        return artifact;
    }

    private ForkStarter createForkStarter( @Nonnull ProviderInfo provider, @Nonnull ForkConfiguration forkConfiguration,
                                           @Nonnull ClassLoaderConfiguration classLoaderConfiguration,
                                           @Nonnull RunOrderParameters runOrderParameters, @Nonnull ConsoleLogger log,
                                           @Nonnull DefaultScanResult scanResult,
                                           @Nonnull TestClassPath testClasspathWrapper, @Nonnull Platform platform,
                                           ResolvePathResultWrapper resolvedJavaModularityResult )
        throws MojoExecutionException, MojoFailureException
    {
        StartupConfiguration startupConfiguration = createStartupConfiguration( provider, true,
                classLoaderConfiguration, scanResult, testClasspathWrapper, platform, resolvedJavaModularityResult );
        String configChecksum = getConfigChecksum();
        StartupReportConfiguration startupReportConfiguration = getStartupReportConfiguration( configChecksum, true );
        ProviderConfiguration providerConfiguration = createProviderConfiguration( runOrderParameters );
        return new ForkStarter( providerConfiguration, startupConfiguration, forkConfiguration,
                                getForkedProcessTimeoutInSeconds(), startupReportConfiguration, log );
    }

    private InPluginVMSurefireStarter createInprocessStarter( @Nonnull ProviderInfo provider,
                                                              @Nonnull ClassLoaderConfiguration classLoaderConfig,
                                                              @Nonnull RunOrderParameters runOrderParameters,
                                                              @Nonnull DefaultScanResult scanResult,
                                                              @Nonnull Platform platform,
                                                              @Nonnull TestClassPath testClasspathWrapper )
        throws MojoExecutionException, MojoFailureException
    {
        StartupConfiguration startupConfiguration = createStartupConfiguration( provider, false, classLoaderConfig,
                scanResult, testClasspathWrapper, platform, new ResolvePathResultWrapper( null, true ) );
        String configChecksum = getConfigChecksum();
        StartupReportConfiguration startupReportConfiguration = getStartupReportConfiguration( configChecksum, false );
        ProviderConfiguration providerConfiguration = createProviderConfiguration( runOrderParameters );
        return new InPluginVMSurefireStarter( startupConfiguration, providerConfiguration, startupReportConfiguration,
                                              getConsoleLogger() );
    }

    // todo this is in separate method and can be better tested than whole method createForkConfiguration()
    @Nonnull
    private ForkNodeFactory getForkNodeFactory()
    {
        ForkNodeFactory forkNode = getForkNode();
        return forkNode == null ? new LegacyForkNodeFactory() : forkNode;
    }

    @Nonnull
    private ForkConfiguration createForkConfiguration( @Nonnull Platform platform,
                                                       @Nonnull ResolvePathResultWrapper resolvedJavaModularityResult )
    {
        File tmpDir = getSurefireTempDir();

        Artifact shadeFire = getShadefireArtifact();

        Classpath bootClasspath = getArtifactClasspath( shadeFire != null ? shadeFire : getBooterArtifact() );

        ForkNodeFactory forkNode = getForkNodeFactory();

        getConsoleLogger().debug( "Found implementation of fork node factory: " + forkNode.getClass().getName() );

        if ( canExecuteProviderWithModularPath( platform, resolvedJavaModularityResult ) )
        {
            return new ModularClasspathForkConfiguration( bootClasspath,
                    tmpDir,
                    getEffectiveDebugForkedProcess(),
                    getWorkingDirectory() != null ? getWorkingDirectory() : getBasedir(),
                    getProject().getModel().getProperties(),
                    getArgLine(),
                    getEnvironmentVariables(),
                    getExcludedEnvironmentVariables(),
                    getConsoleLogger().isDebugEnabled(),
                    getEffectiveForkCount(),
                    reuseForks,
                    platform,
                    getConsoleLogger(),
                    forkNode );
        }
        else if ( getClassLoaderConfiguration().isManifestOnlyJarRequestedAndUsable() )
        {
            return new JarManifestForkConfiguration( bootClasspath,
                    tmpDir,
                    getEffectiveDebugForkedProcess(),
                    getWorkingDirectory() != null ? getWorkingDirectory() : getBasedir(),
                    getProject().getModel().getProperties(),
                    getArgLine(),
                    getEnvironmentVariables(),
                    getExcludedEnvironmentVariables(),
                    getConsoleLogger().isDebugEnabled(),
                    getEffectiveForkCount(),
                    reuseForks,
                    platform,
                    getConsoleLogger(),
                    forkNode );
        }
        else
        {
            return new ClasspathForkConfiguration( bootClasspath,
                    tmpDir,
                    getEffectiveDebugForkedProcess(),
                    getWorkingDirectory() != null ? getWorkingDirectory() : getBasedir(),
                    getProject().getModel().getProperties(),
                    getArgLine(),
                    getEnvironmentVariables(),
                    getExcludedEnvironmentVariables(),
                    getConsoleLogger().isDebugEnabled(),
                    getEffectiveForkCount(),
                    reuseForks,
                    platform,
                    getConsoleLogger(),
                    forkNode );
        }
    }

    private void ensureEnableProcessChecker() throws MojoFailureException
    {
        if ( !ProcessCheckerType.isValid( getEnableProcessChecker() ) )
        {
            throw new MojoFailureException( "Unexpected value '"
                    + getEnableProcessChecker()
                    + "' in the configuration parameter 'enableProcessChecker'." );
        }
    }

    private void convertDeprecatedForkMode()
    {
        String effectiveForkMode = getEffectiveForkMode();
        // FORK_ONCE (default) is represented by the default values of forkCount and reuseForks
        if ( FORK_PERTHREAD.equals( effectiveForkMode ) )
        {
            forkCount = String.valueOf( threadCount );
        }
        else if ( FORK_NEVER.equals( effectiveForkMode ) )
        {
            forkCount = "0";
        }
        else if ( FORK_ALWAYS.equals( effectiveForkMode ) )
        {
            forkCount = "1";
            reuseForks = false;
        }

        if ( !FORK_ONCE.equals( getForkMode() ) )
        {
            getConsoleLogger().warning( "The parameter forkMode is deprecated since version 2.14. "
                                                + "Use forkCount and reuseForks instead." );
        }
    }

    @SuppressWarnings( "checkstyle:emptyblock" )
    protected int getEffectiveForkCount()
    {
        if ( effectiveForkCount < 0 )
        {
            try
            {
                effectiveForkCount = convertWithCoreCount( forkCount );
            }
            catch ( NumberFormatException ignored )
            {
            }

            if ( effectiveForkCount < 0 )
            {
                throw new IllegalArgumentException( "Fork count " + forkCount.trim() + " is not a legal value." );
            }
        }

        return effectiveForkCount;
    }

    protected int convertWithCoreCount( String count )
    {
        String trimmed = count.trim();
        if ( trimmed.endsWith( "C" ) )
        {
            double multiplier = Double.parseDouble( trimmed.substring( 0, trimmed.length() - 1 ) );
            double calculated = multiplier * ( (double) Runtime.getRuntime().availableProcessors() );
            return calculated > 0d ? Math.max( (int) calculated, 1 ) : 0;
        }
        else
        {
            return parseInt( trimmed );
        }
    }

    private String getEffectiveDebugForkedProcess()
    {
        String debugForkedProcess = getDebugForkedProcess();
        if ( "true".equals( debugForkedProcess ) )
        {
            return "-Xdebug -Xnoagent -Djava.compiler=NONE"
                + " -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005";
        }
        return debugForkedProcess;
    }

    private JdkAttributes getEffectiveJvm() throws MojoFailureException
    {
        if ( isNotEmpty( getJvm() ) )
        {
            File pathToJava = new File( getJvm() ).getAbsoluteFile();
            if ( !endsWithJavaPath( pathToJava.getPath() ) )
            {
                throw new MojoFailureException( "Given path does not end with java executor \""
                                                        + pathToJava.getPath() + "\"." );
            }

            if ( !( pathToJava.isFile()
                            || "java".equals( pathToJava.getName() ) && pathToJava.getParentFile().isDirectory() ) )
            {
                throw new MojoFailureException( "Given path to java executor does not exist \""
                                                        + pathToJava.getPath() + "\"." );
            }

            File jdkHome = toJdkHomeFromJvmExec( pathToJava.getPath() );
            if ( jdkHome == null )
            {
                getConsoleLogger().warning( "Cannot determine JAVA_HOME of jvm exec path " + pathToJava );
            }
            else if ( !getEnvironmentVariables().containsKey( "JAVA_HOME" ) )
            {
                getEnvironmentVariables().put( "JAVA_HOME", jdkHome.getAbsolutePath() );
            }
            BigDecimal version = jdkHome == null ? null : toJdkVersionFromReleaseFile( jdkHome );
            boolean javaVersion9 = version == null ? isJava9AtLeast( pathToJava.getPath() ) : isJava9AtLeast( version );
            return new JdkAttributes( pathToJava, jdkHome, javaVersion9 );
        }

        if ( toolchain != null )
        {
            String jvmToUse = toolchain.findTool( "java" );
            if ( isNotEmpty( jvmToUse ) )
            {
                boolean javaVersion9 = false;
                String jdkHome = null;

                if ( toolchain instanceof DefaultToolchain )
                {
                    DefaultToolchain defaultToolchain = (DefaultToolchain) toolchain;
                    javaVersion9 = defaultToolchain.matchesRequirements( JAVA_9_MATCHER )
                                             || defaultToolchain.matchesRequirements( JAVA_9_MATCHER_OLD_NOTATION );
                }

                if ( toolchain instanceof DefaultJavaToolChain )
                {
                    DefaultJavaToolChain defaultJavaToolChain = (DefaultJavaToolChain) toolchain;
                    if ( !getEnvironmentVariables().containsKey( "JAVA_HOME" ) )
                    {
                        jdkHome = defaultJavaToolChain.getJavaHome();
                        getEnvironmentVariables().put( "JAVA_HOME", jdkHome );
                    }
                }

                if ( !javaVersion9 )
                {
                    javaVersion9 = isJava9AtLeast( jvmToUse );
                }

                return new JdkAttributes( new File( jvmToUse ),
                    jdkHome == null ? toJdkHomeFromJvmExec( jvmToUse ) : new File( jdkHome ), javaVersion9 );
            }
        }

        // use the same JVM as the one used to run Maven (the "java.home" one)
        String jvmToUse = System.getProperty( "java.home" ) + File.separator + "bin" + File.separator + "java";
        getConsoleLogger().debug( "Using JVM: " + jvmToUse + " with Java version "
                + JAVA_SPECIFICATION_VERSION.toPlainString() );

        return new JdkAttributes( jvmToUse, isBuiltInJava9AtLeast() );
    }

    /**
     * Where surefire stores its own temp files
     *
     * @return A file pointing to the location of surefire's own temp files
     */
    File getSurefireTempDir()
    {
        File result = IS_OS_WINDOWS ? createSurefireBootDirectoryInTemp() : createSurefireBootDirectoryInBuild();
        try
        {
            File canonical = result.getCanonicalFile();
            if ( !result.equals( canonical ) )
            {
                getConsoleLogger()
                        .debug( "Canonicalized tempDir path '" + result + "' to '" + canonical + "'" );
            }
            return canonical;
        }
        catch ( IOException e )
        {
            getConsoleLogger()
                    .error( "Could not canonicalize tempDir path '" + result + "'", e );
        }
        return result;
    }

    /**
     * Operates on raw plugin parameters, not the "effective" values.
     *
     * @return The checksum
     */
    private String getConfigChecksum()
    {
        ChecksumCalculator checksum = new ChecksumCalculator();
        checksum.add( getPluginName() );
        checksum.add( isSkipTests() );
        checksum.add( isSkipExec() );
        checksum.add( isSkip() );
        checksum.add( getTestClassesDirectory() );
        checksum.add( getMainBuildPath() );
        checksum.add( getClasspathDependencyExcludes() );
        checksum.add( getClasspathDependencyScopeExclude() );
        checksum.add( getAdditionalClasspathElements() );
        checksum.add( getReportsDirectory() );
        checksum.add( getProjectBuildDirectory() );
        checksum.add( getTestSourceDirectory() );
        checksum.add( getTest() );
        checksum.add( getIncludes() );
        checksum.add( getSkipAfterFailureCount() );
        checksum.add( getShutdown() );
        checksum.add( getExcludes() );
        checksum.add( getLocalRepository() );
        checksum.add( getSystemProperties() );
        checksum.add( getSystemPropertyVariables() );
        checksum.add( getSystemPropertiesFile() );
        checksum.add( getProperties() );
        checksum.add( isPrintSummary() );
        checksum.add( getReportFormat() );
        checksum.add( getReportNameSuffix() );
        checksum.add( isUseFile() );
        checksum.add( isRedirectTestOutputToFile() );
        checksum.add( getForkMode() );
        checksum.add( getForkCount() );
        checksum.add( isReuseForks() );
        checksum.add( getJvm() );
        checksum.add( getArgLine() );
        checksum.add( getDebugForkedProcess() );
        checksum.add( getForkedProcessTimeoutInSeconds() );
        checksum.add( getParallelTestsTimeoutInSeconds() );
        checksum.add( getParallelTestsTimeoutForcedInSeconds() );
        checksum.add( getEnvironmentVariables() );
        checksum.add( getExcludedEnvironmentVariables() );
        checksum.add( getWorkingDirectory() );
        checksum.add( isChildDelegation() );
        checksum.add( getGroups() );
        checksum.add( getExcludedGroups() );
        checksum.add( getSuiteXmlFiles() );
        checksum.add( getJunitArtifact() );
        checksum.add( getTestNGArtifactName() );
        checksum.add( getThreadCount() );
        checksum.add( getThreadCountSuites() );
        checksum.add( getThreadCountClasses() );
        checksum.add( getThreadCountMethods() );
        checksum.add( getPerCoreThreadCount() );
        checksum.add( getUseUnlimitedThreads() );
        checksum.add( getParallel() );
        checksum.add( isParallelOptimized() );
        checksum.add( isTrimStackTrace() );
        checksum.add( getRemoteRepositories() );
        checksum.add( getProjectRemoteRepositories() );
        checksum.add( isDisableXmlReport() );
        checksum.add( isUseSystemClassLoader() );
        checksum.add( isUseManifestOnlyJar() );
        checksum.add( getEncoding() );
        checksum.add( isEnableAssertions() );
        checksum.add( getObjectFactory() );
        checksum.add( getFailIfNoTests() );
        checksum.add( getRunOrder() );
        checksum.add( getDependenciesToScan() );
        checksum.add( getForkedProcessExitTimeoutInSeconds() );
        checksum.add( getRerunFailingTestsCount() );
        checksum.add( getTempDir() );
        checksum.add( useModulePath() );
        checksum.add( getEnableProcessChecker() );
        addPluginSpecificChecksumItems( checksum );
        return checksum.getSha1();
    }

    protected void addPluginSpecificChecksumItems( ChecksumCalculator checksum )
    {

    }

    protected boolean hasExecutedBefore()
    {
        // A tribute to Linus Torvalds
        String configChecksum = getConfigChecksum();
        @SuppressWarnings( "unchecked" ) Map<String, String> pluginContext = getPluginContext();
        if ( pluginContext.containsKey( configChecksum ) )
        {
            getConsoleLogger()
                    .info( "Skipping execution of surefire because it has already been run for this configuration" );
            return true;
        }
        pluginContext.put( configChecksum, configChecksum );

        return false;
    }

    @Nonnull
    protected ClassLoaderConfiguration getClassLoaderConfiguration()
    {
        return isForking()
            ? new ClassLoaderConfiguration( isUseSystemClassLoader(), isUseManifestOnlyJar() )
            : new ClassLoaderConfiguration( false, false );
    }

    /**
     * Generates the test classpath.
     *
     * @return the classpath elements
     */
    private TestClassPath generateTestClasspath()
    {
        Set<Artifact> classpathArtifacts = getProject().getArtifacts();

        if ( getClasspathDependencyScopeExclude() != null && !getClasspathDependencyScopeExclude().isEmpty() )
        {
            ArtifactFilter dependencyFilter = new ScopeArtifactFilter( getClasspathDependencyScopeExclude() );
            classpathArtifacts = filterArtifacts( classpathArtifacts, dependencyFilter );
        }

        if ( getClasspathDependencyExcludes() != null )
        {
            List<String> excludedDependencies = asList( getClasspathDependencyExcludes() );
            ArtifactFilter dependencyFilter = new PatternIncludesArtifactFilter( excludedDependencies );
            classpathArtifacts = filterArtifacts( classpathArtifacts, dependencyFilter );
        }

        return new TestClassPath( classpathArtifacts, getMainBuildPath(),
                getTestClassesDirectory(), getAdditionalClasspathElements() );
    }

    /**
     * Return a new set containing only the artifacts accepted by the given filter.
     *
     * @param artifacts The unfiltered artifacts
     * @param filter    The filter to apply
     * @return The filtered result
     */
    private static Set<Artifact> filterArtifacts( Set<Artifact> artifacts, ArtifactFilter filter )
    {
        Set<Artifact> filteredArtifacts = new LinkedHashSet<>();

        for ( Artifact artifact : artifacts )
        {
            if ( !filter.include( artifact ) )
            {
                filteredArtifacts.add( artifact );
            }
        }

        return filteredArtifacts;
    }

    private void showMap( Map<?, ?> map, String setting )
    {
        for ( Object o : map.keySet() )
        {
            String key = (String) o;
            String value = (String) map.get( key );
            getConsoleLogger().debug( "Setting " + setting + " [" + key + "]=[" + value + "]" );
        }
    }

    private <T> void showArray( T[] array, String setting )
    {
        for ( T e : array )
        {
            getConsoleLogger().debug( "Setting " + setting + " [" + e + "]" );
        }
    }

    private Classpath getArtifactClasspath( Artifact surefireArtifact )
    {
        Classpath existing = classpathCache.getCachedClassPath( surefireArtifact.getArtifactId() );
        if ( existing == null )
        {
            List<String> items = new ArrayList<>();
            Set<Artifact> booterArtifacts =
                    surefireDependencyResolver.resolvePluginArtifact( surefireArtifact ).getArtifacts();
            for ( Artifact artifact : booterArtifacts )
            {
                getConsoleLogger().debug(
                    "Adding to " + getPluginName() + " booter test classpath: " + artifact.getFile().getAbsolutePath()
                    + " Scope: " + artifact.getScope() );
                items.add( artifact.getFile().getAbsolutePath() );
            }
            existing = new Classpath( items );
            classpathCache.setCachedClasspath( surefireArtifact.getArtifactId(), existing );
        }
        return existing;
    }

    private Properties getUserProperties()
    {
        return getSession().getUserProperties();
    }

    private void ensureWorkingDirectoryExists()
        throws MojoFailureException
    {
        if ( getWorkingDirectory() == null )
        {
            throw new MojoFailureException( "workingDirectory cannot be null" );
        }

        if ( isForking() )
        {
            // Postpone directory creation till forked JVM creation
            // see ForkConfiguration.createCommandLine
            return;
        }

        if ( !getWorkingDirectory().exists() )
        {
            if ( !getWorkingDirectory().mkdirs() )
            {
                throw new MojoFailureException( "Cannot create workingDirectory " + getWorkingDirectory() );
            }
        }

        if ( !getWorkingDirectory().isDirectory() )
        {
            throw new MojoFailureException(
                "workingDirectory " + getWorkingDirectory() + " exists and is not a directory" );
        }
    }

    private void ensureParallelRunningCompatibility()
        throws MojoFailureException
    {
        if ( isMavenParallel() && isNotForking() )
        {
            throw new MojoFailureException( "parallel maven execution is not compatible with surefire forkCount 0" );
        }
    }

    private void ensureThreadCountWithPerThread()
        throws MojoFailureException
    {
        if ( FORK_PERTHREAD.equals( getEffectiveForkMode() ) && getThreadCount() < 1 )
        {
            throw new MojoFailureException( "Fork mode perthread requires a thread count" );
        }
    }

    private void warnIfUselessUseSystemClassLoaderParameter()
    {
        if ( isUseSystemClassLoader() && isNotForking() )
        {
            getConsoleLogger().warning( "useSystemClassLoader setting has no effect when not forking" );
        }
    }

    private boolean isNotForking()
    {
        return !isForking();
    }

    private List<CommandLineOption> commandLineOptions()
    {
        return SurefireHelper.commandLineOptions( getSession(), getConsoleLogger() );
    }

    private void warnIfDefunctGroupsCombinations()
        throws MojoFailureException, MojoExecutionException
    {
        if ( isAnyGroupsSelected() )
        {
            if ( getTestNgArtifact() == null )
            {
                Artifact junitArtifact = getJunitArtifact();
                boolean junit47Compatible = isJunit47Compatible( junitArtifact );
                boolean junit5PlatformCompatible = getJUnit5Artifact() != null;
                if ( !junit47Compatible && !junit5PlatformCompatible )
                {
                    if ( junitArtifact != null )
                    {
                        throw new MojoFailureException( "groups/excludedGroups are specified but JUnit version on "
                                                            + "classpath is too old to support groups. "
                                                            + "Check your dependency:tree to see if your project "
                                                            + "is picking up an old junit version" );
                    }
                    throw new MojoFailureException( "groups/excludedGroups require TestNG, JUnit48+ or JUnit 5 "
                            + "(a specific engine required on classpath) on project test classpath" );
                }
            }

        }
    }

    private void warnIfRerunClashes()
        throws MojoFailureException
    {
        if ( getRerunFailingTestsCount() < 0 )
        {
            throw new MojoFailureException( "Parameter \"rerunFailingTestsCount\" should not be negative." );
        }

        if ( getSkipAfterFailureCount() < 0 )
        {
            throw new MojoFailureException( "Parameter \"skipAfterFailureCount\" should not be negative." );
        }
    }

    private void warnIfWrongShutdownValue()
        throws MojoFailureException
    {
        if ( !Shutdown.isKnown( getShutdown() ) )
        {
            throw new MojoFailureException( "Parameter \"shutdown\" should have values " + Shutdown.listParameters() );
        }
    }

    private void warnIfNotApplicableSkipAfterFailureCount()
        throws MojoFailureException
    {
        int skipAfterFailureCount = getSkipAfterFailureCount();

        if ( skipAfterFailureCount < 0 )
        {
            throw new MojoFailureException( "Parameter \"skipAfterFailureCount\" should not be negative." );
        }
        else if ( skipAfterFailureCount > 0 )
        {
            try
            {
                Artifact testng = getTestNgArtifact();
                if ( testng != null )
                {
                    VersionRange range = VersionRange.createFromVersionSpec( "[5.10,)" );
                    if ( !range.containsVersion( new DefaultArtifactVersion( testng.getVersion() ) ) )
                    {
                        throw new MojoFailureException(
                            "Parameter \"skipAfterFailureCount\" expects TestNG Version 5.10 or higher. "
                                + "java.lang.NoClassDefFoundError: org/testng/IInvokedMethodListener" );
                    }
                }
                else
                {
                    // TestNG is dependent on JUnit
                    Artifact junit = getJunitArtifact();
                    if ( junit != null )
                    {
                        VersionRange range = VersionRange.createFromVersionSpec( "[4.0,)" );
                        if ( !range.containsVersion( new DefaultArtifactVersion( junit.getVersion() ) ) )
                        {
                            throw new MojoFailureException(
                                "Parameter \"skipAfterFailureCount\" expects JUnit Version 4.0 or higher. "
                                    + "java.lang.NoSuchMethodError: "
                                    + "org.junit.runner.notification.RunNotifier.pleaseStop()V" );
                        }
                    }
                }
            }
            catch ( MojoExecutionException e )
            {
                throw new MojoFailureException( e.getLocalizedMessage() );
            }
            catch ( InvalidVersionSpecificationException e )
            {
                throw new RuntimeException( e );
            }
        }
    }

    private void warnIfIllegalTempDir() throws MojoFailureException
    {
        if ( isEmpty( getTempDir() ) )
        {
            throw new MojoFailureException( "Parameter 'tempDir' should not be blank string." );
        }
    }

    final class TestNgProviderInfo
        implements ProviderInfo
    {
        private final Artifact testNgArtifact;

        TestNgProviderInfo( Artifact testNgArtifact )
        {
            this.testNgArtifact = testNgArtifact;
        }

        @Override
        @Nonnull public String getProviderName()
        {
            return "org.apache.maven.surefire.testng.TestNGProvider";
        }

        @Override
        public boolean isApplicable()
        {
            return testNgArtifact != null;
        }

        @Override
        public void addProviderProperties() throws MojoExecutionException
        {
            convertTestNGParameters();
        }

        @Override
        @Nonnull
        public Set<Artifact> getProviderClasspath()
        {
            Artifact surefireArtifact = getBooterArtifact();
            String version = surefireArtifact.getBaseVersion();
            return surefireDependencyResolver.getProviderClasspath( "surefire-testng", version );
        }
    }

    final class JUnit3ProviderInfo
        implements ProviderInfo
    {
        @Override
        @Nonnull public String getProviderName()
        {
            return "org.apache.maven.surefire.junit.JUnit3Provider";
        }

        @Override
        public boolean isApplicable()
        {
            return true;
        }

        @Override
        public void addProviderProperties()
        {
        }

        @Override
        @Nonnull
        public Set<Artifact> getProviderClasspath()
        {
            // add the JUnit provider as default - it doesn't require JUnit to be present,
            // since it supports POJO tests.
            String version = getBooterArtifact().getBaseVersion();
            return surefireDependencyResolver.getProviderClasspath( "surefire-junit3", version );
        }
    }

    final class JUnit4ProviderInfo
        implements ProviderInfo
    {
        private final Artifact junitArtifact;

        private final Artifact junitDepArtifact;

        JUnit4ProviderInfo( Artifact junitArtifact, Artifact junitDepArtifact )
        {
            this.junitArtifact = junitArtifact;
            this.junitDepArtifact = junitDepArtifact;
        }

        @Override
        @Nonnull public String getProviderName()
        {
            return "org.apache.maven.surefire.junit4.JUnit4Provider";
        }

        @Override
        public boolean isApplicable()
        {
            return junitDepArtifact != null || isAnyJunit4( junitArtifact );
        }

        @Override
        public void addProviderProperties()
        {
        }

        @Override
        @Nonnull
        public Set<Artifact> getProviderClasspath()
        {
            String version = getBooterArtifact().getBaseVersion();
            return surefireDependencyResolver.getProviderClasspath( "surefire-junit4", version );
        }
    }

    final class JUnitPlatformProviderInfo
        implements ProviderInfo
    {
        private static final String PROVIDER_DEP_GID = "org.junit.platform";
        private static final String PROVIDER_DEP_AID = "junit-platform-launcher";

        private final Artifact junitPlatformArtifact;
        private final TestClassPath testClasspath;

        JUnitPlatformProviderInfo( Artifact junitPlatformArtifact, @Nonnull TestClassPath testClasspath )
        {
            this.junitPlatformArtifact = junitPlatformArtifact;
            this.testClasspath = testClasspath;
        }

        @Override
        @Nonnull
        public String getProviderName()
        {
            return "org.apache.maven.surefire.junitplatform.JUnitPlatformProvider";
        }

        @Override
        public boolean isApplicable()
        {
            return junitPlatformArtifact != null;
        }

        @Override
        public void addProviderProperties()
        {
            convertGroupParameters();
        }

        @Override
        @Nonnull
        public Set<Artifact> getProviderClasspath() throws MojoExecutionException
        {
            String surefireVersion = getBooterArtifact().getBaseVersion();
            Map<String, Artifact> providerArtifacts =
                    surefireDependencyResolver.getProviderClasspathAsMap( "surefire-junit-platform", surefireVersion );
            Map<String, Artifact> testDeps = testClasspath.getTestDependencies();

            ProjectBuildingRequest request = getSession().getProjectBuildingRequest();
            Plugin plugin = getPluginDescriptor().getPlugin();
            Map<String, Artifact> pluginDeps =
                surefireDependencyResolver.resolvePluginDependencies( request, plugin, getPluginArtifactMap() );

            if ( hasDependencyPlatformEngine( pluginDeps ) )
            {
                providerArtifacts.putAll( pluginDeps );
            }
            else
            {
                String engineVersion = null;
                if ( hasDependencyJupiterAPI( testDeps )
                    && !testDeps.containsKey( "org.junit.jupiter:junit-jupiter-engine" ) )
                {
                    String engineGroupId = "org.junit.jupiter";
                    String engineArtifactId = "junit-jupiter-engine";
                    String engineCoordinates = engineGroupId + ":" + engineArtifactId;
                    String api = "org.junit.jupiter:junit-jupiter-api";
                    engineVersion = testDeps.get( api ).getBaseVersion();
                    getConsoleLogger().debug( "Test dependencies contain "
                        + api + ". Resolving " + engineCoordinates + ":" + engineVersion );
                    addEngineByApi( engineGroupId, engineArtifactId, engineVersion, providerArtifacts );
                }

                if ( ( testDeps.containsKey( "junit:junit" ) || testDeps.containsKey( "junit:junit-dep" ) )
                    && !testDeps.containsKey( "org.junit.vintage:junit-vintage-engine" ) )
                {
                    String engineGroupId = "org.junit.vintage";
                    String engineArtifactId = "junit-vintage-engine";
                    String engineCoordinates = engineGroupId + ":" + engineArtifactId;

                    if ( engineVersion != null )
                    {
                        getConsoleLogger().debug( "Test dependencies contain JUnit4. Resolving "
                            + engineCoordinates + ":" + engineVersion );
                        addEngineByApi( engineGroupId, engineArtifactId, engineVersion, providerArtifacts );
                    }
                }
            }

            narrowDependencies( providerArtifacts, testDeps );
            alignProviderVersions( providerArtifacts );

            return new LinkedHashSet<>( providerArtifacts.values() );
        }

        private void addEngineByApi( String engineGroupId, String engineArtifactId, String engineVersion,
                                     Map<String, Artifact> providerArtifacts )
        {
            for ( Artifact dep : resolve( engineGroupId, engineArtifactId, engineVersion, null, "jar" ) )
            {
                String key = dep.getGroupId() + ":" + dep.getArtifactId();
                providerArtifacts.put( key, dep );
            }
        }

        private void narrowDependencies( Map<String, Artifact> providerArtifacts,
                                         Map<String, Artifact> testDependencies )
        {
            providerArtifacts.keySet().removeAll( testDependencies.keySet() );
        }

        private void alignProviderVersions( Map<String, Artifact> providerArtifacts )
        {
            String version = junitPlatformArtifact.getBaseVersion();
            for ( Artifact launcherArtifact : resolve( PROVIDER_DEP_GID, PROVIDER_DEP_AID, version, null, "jar" ) )
            {
                String key = launcherArtifact.getGroupId() + ":" + launcherArtifact.getArtifactId();
                if ( providerArtifacts.containsKey( key ) )
                {
                    providerArtifacts.put( key, launcherArtifact );
                }
            }
        }

        private Set<Artifact> resolve( String g, String a, String v, String c, String t )
        {
            ArtifactHandler handler = junitPlatformArtifact.getArtifactHandler();
            Artifact artifact = new DefaultArtifact( g, a, v, null, t, c, handler );
            getConsoleLogger().debug( "Resolving artifact " + g + ":" + a + ":" + v );
            Set<Artifact> r = surefireDependencyResolver.resolveProjectArtifact( artifact ).getArtifacts();
            getConsoleLogger().debug( "Resolved artifact " + g + ":" + a + ":" + v + " to " + r );
            return r;
        }

        private boolean hasDependencyJupiterAPI( Map<String, Artifact> dependencies )
        {
            return dependencies.containsKey( "org.junit.jupiter:junit-jupiter-api" );
        }

        private boolean hasDependencyPlatformEngine( Map<String, Artifact> dependencies )
        {
            for ( Entry<String, Artifact> dependency : dependencies.entrySet() )
            {
                if ( dependency.getKey().equals( "org.junit.platform:junit-platform-engine" ) )
                {
                    return true;
                }
            }

            return false;
        }
    }

    final class JUnitCoreProviderInfo
        implements ProviderInfo
    {
        private final Artifact junitArtifact;

        private final Artifact junitDepArtifact;

        JUnitCoreProviderInfo( Artifact junitArtifact, Artifact junitDepArtifact )
        {
            this.junitArtifact = junitArtifact;
            this.junitDepArtifact = junitDepArtifact;
        }

        @Override
        @Nonnull public String getProviderName()
        {
            return "org.apache.maven.surefire.junitcore.JUnitCoreProvider";
        }

        private boolean is47CompatibleJunitDep()
        {
            return isJunit47Compatible( junitDepArtifact );
        }

        @Override
        public boolean isApplicable()
        {
            final boolean isJunitArtifact47 = isAnyJunit4( junitArtifact ) && isJunit47Compatible( junitArtifact );
            final boolean isAny47ProvidersForces = isAnyConcurrencySelected() || isAnyGroupsSelected();
            return isAny47ProvidersForces && ( isJunitArtifact47 || is47CompatibleJunitDep() );
        }

        @Override
        public void addProviderProperties() throws MojoExecutionException
        {
            convertJunitCoreParameters();
            convertGroupParameters();
        }

        @Override
        @Nonnull
        public Set<Artifact> getProviderClasspath()
        {
            String version = getBooterArtifact().getBaseVersion();
            return surefireDependencyResolver.getProviderClasspath( "surefire-junit47", version );
        }
    }

    /**
     * Provides the Provider information for manually configured providers.
     */
    final class DynamicProviderInfo
        implements ConfigurableProviderInfo
    {
        final String providerName;

        DynamicProviderInfo( String providerName )
        {
            this.providerName = providerName;
        }

        @Override
        public ProviderInfo instantiate( String providerName )
        {
            return new DynamicProviderInfo( providerName );
        }

        @Override
        @Nonnull
        public String getProviderName()
        {
            return providerName;
        }

        @Override
        public boolean isApplicable()
        {
            return true;
        }

        @Override
        public void addProviderProperties() throws MojoExecutionException
        {
            // Ok this is a bit lazy.
            convertJunitCoreParameters();
            convertTestNGParameters();
        }

        @Override
        @Nonnull
        public Set<Artifact> getProviderClasspath() throws MojoExecutionException
        {
            ProjectBuildingRequest request = getSession().getProjectBuildingRequest();
            Plugin plugin = getPluginDescriptor().getPlugin();
            Map<String, Artifact> providerArtifacts =
                surefireDependencyResolver.resolvePluginDependencies( request, plugin, getPluginArtifactMap() );
            return new LinkedHashSet<>( providerArtifacts.values() );
        }
    }

    /**
     * @author Kristian Rosenvold
     */
    final class ProviderList
    {
        private final ProviderInfo[] wellKnownProviders;

        private final ConfigurableProviderInfo dynamicProvider;

        ProviderList( ConfigurableProviderInfo dynamicProviderInfo, ProviderInfo... wellKnownProviders )
        {
            this.wellKnownProviders = wellKnownProviders;
            this.dynamicProvider = dynamicProviderInfo;
        }

        @Nonnull List<ProviderInfo> resolve()
        {
            List<ProviderInfo> providersToRun = new ArrayList<>();
            Set<String> manuallyConfiguredProviders = getManuallyConfiguredProviders();
            for ( String name : manuallyConfiguredProviders )
            {
                ProviderInfo wellKnown = findByName( name );
                ProviderInfo providerToAdd = wellKnown != null ? wellKnown : dynamicProvider.instantiate( name );
                logDebugOrCliShowErrors( "Using configured provider " + providerToAdd.getProviderName() );
                providersToRun.add( providerToAdd );
            }
            return manuallyConfiguredProviders.isEmpty() ? autoDetectOneWellKnownProvider() : providersToRun;
        }

        @Nonnull private List<ProviderInfo> autoDetectOneWellKnownProvider()
        {
            List<ProviderInfo> providersToRun = new ArrayList<>();
            for ( ProviderInfo wellKnownProvider : wellKnownProviders )
            {
                if ( wellKnownProvider.isApplicable() )
                {
                    providersToRun.add( wellKnownProvider );
                    return providersToRun;
                }
            }
            return providersToRun;
        }

        private Set<String> getManuallyConfiguredProviders()
        {
            try
            {
                ClassLoader cl = currentThread().getContextClassLoader();
                return providerDetector.lookupServiceNames( SurefireProvider.class, cl );
            }
            catch ( IOException e )
            {
                throw new RuntimeException( e );
            }
        }

        private ProviderInfo findByName( String providerClassName )
        {
            for ( ProviderInfo wellKnownProvider : wellKnownProviders )
            {
                if ( wellKnownProvider.getProviderName().equals( providerClassName ) )
                {
                    return wellKnownProvider;
                }
            }
            return null;
        }
    }

    File createSurefireBootDirectoryInBuild()
    {
        File tmp = new File( getProjectBuildDirectory(), getTempDir() );
        //noinspection ResultOfMethodCallIgnored
        tmp.mkdirs();
        return tmp;
    }

    File createSurefireBootDirectoryInTemp()
    {
        try
        {
            return Files.createTempDirectory( getTempDir() ).toFile();
        }
        catch ( IOException e )
        {
            return createSurefireBootDirectoryInBuild();
        }
    }

    @Override
    public List<String> getExcludes()
    {
        return excludes;
    }

    @Override
    public void setExcludes( List<String> excludes )
    {
        this.excludes = excludes;
    }

    @Override
    public ArtifactRepository getLocalRepository()
    {
        return localRepository;
    }

    @Override
    public void setLocalRepository( ArtifactRepository localRepository )
    {
        this.localRepository = localRepository;
    }

    public Properties getSystemProperties()
    {
        return systemProperties;
    }

    @SuppressWarnings( "UnusedDeclaration" )
    public void setSystemProperties( Properties systemProperties )
    {
        this.systemProperties = systemProperties;
    }

    public Map<String, String> getSystemPropertyVariables()
    {
        return systemPropertyVariables;
    }

    @SuppressWarnings( "UnusedDeclaration" )
    public void setSystemPropertyVariables( Map<String, String> systemPropertyVariables )
    {
        this.systemPropertyVariables = systemPropertyVariables;
    }

    /**
     * List of System properties, loaded from a file, to pass to the JUnit tests.
     *
     * @since 2.8.2
     */
    public abstract File getSystemPropertiesFile();

    @SuppressWarnings( "UnusedDeclaration" )
    public abstract void setSystemPropertiesFile( File systemPropertiesFile );

    private Properties getProperties()
    {
        return properties;
    }

    public void setProperties( Properties properties )
    {
        this.properties = properties;
    }

    public Map<String, Artifact> getPluginArtifactMap()
    {
        return pluginArtifactMap;
    }

    @SuppressWarnings( "UnusedDeclaration" )
    public void setPluginArtifactMap( Map<String, Artifact> pluginArtifactMap )
    {
        this.pluginArtifactMap = pluginArtifactMap;
    }

    public Map<String, Artifact> getProjectArtifactMap()
    {
        return projectArtifactMap;
    }

    @SuppressWarnings( "UnusedDeclaration" )
    public void setProjectArtifactMap( Map<String, Artifact> projectArtifactMap )
    {
        this.projectArtifactMap = projectArtifactMap;
    }

    public String getReportNameSuffix()
    {
        return reportNameSuffix;
    }

    @SuppressWarnings( "UnusedDeclaration" )
    public void setReportNameSuffix( String reportNameSuffix )
    {
        this.reportNameSuffix = reportNameSuffix;
    }


    public boolean isRedirectTestOutputToFile()
    {
        return redirectTestOutputToFile;
    }

    @SuppressWarnings( "UnusedDeclaration" )
    public void setRedirectTestOutputToFile( boolean redirectTestOutputToFile )
    {
        this.redirectTestOutputToFile = redirectTestOutputToFile;
    }


    public Boolean getFailIfNoTests()
    {
        return failIfNoTests;
    }

    public void setFailIfNoTests( boolean failIfNoTests )
    {
        this.failIfNoTests = failIfNoTests;
    }

    public String getForkMode()
    {
        return forkMode;
    }

    @SuppressWarnings( "UnusedDeclaration" )
    public void setForkMode( String forkMode )
    {
        this.forkMode = forkMode;
    }

    public String getJvm()
    {
        return jvm;
    }

    public String getArgLine()
    {
        return argLine;
    }

    @SuppressWarnings( "UnusedDeclaration" )
    public void setArgLine( String argLine )
    {
        this.argLine = argLine;
    }


    public Map<String, String> getEnvironmentVariables()
    {
        return environmentVariables;
    }

    @SuppressWarnings( "UnusedDeclaration" )
    public void setEnvironmentVariables( Map<String, String> environmentVariables )
    {
        this.environmentVariables = environmentVariables;
    }

    public File getWorkingDirectory()
    {
        return workingDirectory;
    }

    @SuppressWarnings( "UnusedDeclaration" )
    public void setWorkingDirectory( File workingDirectory )
    {
        this.workingDirectory = workingDirectory;
    }

    public boolean isChildDelegation()
    {
        return childDelegation;
    }

    @SuppressWarnings( "UnusedDeclaration" )
    public void setChildDelegation( boolean childDelegation )
    {
        this.childDelegation = childDelegation;
    }

    public String getGroups()
    {
        return groups;
    }

    @SuppressWarnings( "UnusedDeclaration" )
    public void setGroups( String groups )
    {
        this.groups = groups;
    }

    public String getExcludedGroups()
    {
        return excludedGroups;
    }

    @SuppressWarnings( "UnusedDeclaration" )
    public void setExcludedGroups( String excludedGroups )
    {
        this.excludedGroups = excludedGroups;
    }

    public String getJunitArtifactName()
    {
        return junitArtifactName;
    }

    @SuppressWarnings( "UnusedDeclaration" )
    public void setJunitArtifactName( String junitArtifactName )
    {
        this.junitArtifactName = junitArtifactName;
    }

    public String getTestNGArtifactName()
    {
        return testNGArtifactName;
    }

    @SuppressWarnings( "UnusedDeclaration" )
    public void setTestNGArtifactName( String testNGArtifactName )
    {
        this.testNGArtifactName = testNGArtifactName;
    }

    public int getThreadCount()
    {
        return threadCount;
    }

    @SuppressWarnings( "UnusedDeclaration" )
    public void setThreadCount( int threadCount )
    {
        this.threadCount = threadCount;
    }

    public boolean getPerCoreThreadCount()
    {
        return perCoreThreadCount;
    }

    @SuppressWarnings( "UnusedDeclaration" )
    public void setPerCoreThreadCount( boolean perCoreThreadCount )
    {
        this.perCoreThreadCount = perCoreThreadCount;
    }

    public boolean getUseUnlimitedThreads()
    {
        return useUnlimitedThreads;
    }

    @SuppressWarnings( "UnusedDeclaration" )
    public void setUseUnlimitedThreads( boolean useUnlimitedThreads )
    {
        this.useUnlimitedThreads = useUnlimitedThreads;
    }

    public String getParallel()
    {
        return parallel;
    }

    @SuppressWarnings( "UnusedDeclaration" )
    public void setParallel( String parallel )
    {
        this.parallel = parallel;
    }

    public boolean isParallelOptimized()
    {
        return parallelOptimized;
    }

    @SuppressWarnings( "UnusedDeclaration" )
    public void setParallelOptimized( boolean parallelOptimized )
    {
        this.parallelOptimized = parallelOptimized;
    }

    public int getThreadCountSuites()
    {
        return threadCountSuites;
    }

    public void setThreadCountSuites( int threadCountSuites )
    {
        this.threadCountSuites = threadCountSuites;
    }

    public int getThreadCountClasses()
    {
        return threadCountClasses;
    }

    public void setThreadCountClasses( int threadCountClasses )
    {
        this.threadCountClasses = threadCountClasses;
    }

    public int getThreadCountMethods()
    {
        return threadCountMethods;
    }

    public void setThreadCountMethods( int threadCountMethods )
    {
        this.threadCountMethods = threadCountMethods;
    }

    public boolean isTrimStackTrace()
    {
        return trimStackTrace;
    }

    @SuppressWarnings( "UnusedDeclaration" )
    public void setTrimStackTrace( boolean trimStackTrace )
    {
        this.trimStackTrace = trimStackTrace;
    }

    public List<ArtifactRepository> getProjectRemoteRepositories()
    {
        return projectRemoteRepositories;
    }

    @SuppressWarnings( "UnusedDeclaration" )
    public void setProjectRemoteRepositories( List<ArtifactRepository> projectRemoteRepositories )
    {
        this.projectRemoteRepositories = projectRemoteRepositories;
    }

    public List<ArtifactRepository> getRemoteRepositories()
    {
        return remoteRepositories;
    }

    @SuppressWarnings( "UnusedDeclaration" )
    public void setRemoteRepositories( List<ArtifactRepository> remoteRepositories )
    {
        this.remoteRepositories = remoteRepositories;
    }

    public boolean isDisableXmlReport()
    {
        return disableXmlReport;
    }

    @SuppressWarnings( "UnusedDeclaration" )
    public void setDisableXmlReport( boolean disableXmlReport )
    {
        this.disableXmlReport = disableXmlReport;
    }


    public boolean isEnableAssertions()
    {
        return enableAssertions;
    }

    public boolean effectiveIsEnableAssertions()
    {
        if ( getArgLine() != null )
        {
            List<String> args = asList( getArgLine().split( " " ) );
            if ( args.contains( "-da" ) || args.contains( "-disableassertions" ) )
            {
                return false;
            }
        }
        return isEnableAssertions();
    }

    @SuppressWarnings( "UnusedDeclaration" )
    public void setEnableAssertions( boolean enableAssertions )
    {
        this.enableAssertions = enableAssertions;
    }

    public MavenSession getSession()
    {
        return session;
    }

    @SuppressWarnings( "UnusedDeclaration" )
    public void setSession( MavenSession session )
    {
        this.session = session;
    }

    public String getObjectFactory()
    {
        return objectFactory;
    }

    @SuppressWarnings( "UnusedDeclaration" )
    public void setObjectFactory( String objectFactory )
    {
        this.objectFactory = objectFactory;
    }

    public ToolchainManager getToolchainManager()
    {
        return toolchainManager;
    }

    @SuppressWarnings( "UnusedDeclaration" )
    public void setToolchainManager( ToolchainManager toolchainManager )
    {
        this.toolchainManager = toolchainManager;
    }

    public boolean isMavenParallel()
    {
        return parallelMavenExecution != null && parallelMavenExecution;
    }

    public String[] getDependenciesToScan()
    {
        return dependenciesToScan;
    }

    public void setDependenciesToScan( String[] dependenciesToScan )
    {
        this.dependenciesToScan = dependenciesToScan;
    }

    @SuppressWarnings( "UnusedDeclaration" )
    void setPluginDescriptor( PluginDescriptor pluginDescriptor )
    {
        this.pluginDescriptor = pluginDescriptor;
    }

    public PluginDescriptor getPluginDescriptor()
    {
        return pluginDescriptor;
    }

    public MavenProject getProject()
    {
        return project;
    }

    @SuppressWarnings( "UnusedDeclaration" )
    public void setProject( MavenProject project )
    {
        this.project = project;
    }

    @Override
    public File getTestSourceDirectory()
    {
        return testSourceDirectory;
    }

    @Override
    public void setTestSourceDirectory( File testSourceDirectory )
    {
        this.testSourceDirectory = testSourceDirectory;
    }

    public String getForkCount()
    {
        return forkCount;
    }

    public boolean isReuseForks()
    {
        return reuseForks;
    }

    public String[] getAdditionalClasspathElements()
    {
        return additionalClasspathElements;
    }

    public void setAdditionalClasspathElements( String[] additionalClasspathElements )
    {
        this.additionalClasspathElements = additionalClasspathElements;
    }

    public String[] getClasspathDependencyExcludes()
    {
        return classpathDependencyExcludes;
    }

    public void setClasspathDependencyExcludes( String[] classpathDependencyExcludes )
    {
        this.classpathDependencyExcludes = classpathDependencyExcludes;
    }

    public String getClasspathDependencyScopeExclude()
    {
        return classpathDependencyScopeExclude;
    }

    public void setClasspathDependencyScopeExclude( String classpathDependencyScopeExclude )
    {
        this.classpathDependencyScopeExclude = classpathDependencyScopeExclude;
    }

    public File getProjectBuildDirectory()
    {
        return projectBuildDirectory;
    }

    public void setProjectBuildDirectory( File projectBuildDirectory )
    {
        this.projectBuildDirectory = projectBuildDirectory;
    }

    protected void logDebugOrCliShowErrors( String s )
    {
        SurefireHelper.logDebugOrCliShowErrors( s, getConsoleLogger(), cli );
    }

    public Map<String, String> getJdkToolchain()
    {
        return jdkToolchain;
    }

    public void setJdkToolchain( Map<String, String> jdkToolchain )
    {
        this.jdkToolchain = jdkToolchain;
    }

    public String getTempDir()
    {
        return tempDir;
    }

    public void setTempDir( String tempDir )
    {
        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" );
        }
    }

    private static final class ClasspathCache
    {
        private final Map<String, Classpath> classpaths = new HashMap<>( 4 );

        private Classpath getCachedClassPath( @Nonnull String artifactId )
        {
            return classpaths.get( artifactId );
        }

        private void setCachedClasspath( @Nonnull String key, @Nonnull Classpath classpath )
        {
            classpaths.put( key, classpath );
        }

        private Classpath setCachedClasspath( @Nonnull String key, @Nonnull Set<Artifact> artifacts )
        {
            Collection<String> files = new ArrayList<>();
            for ( Artifact artifact : artifacts )
            {
                files.add( artifact.getFile().getAbsolutePath() );
            }
            Classpath classpath = new Classpath( files );
            setCachedClasspath( key, classpath );
            return classpath;
        }
    }
}
