// 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.booter.ProviderParameterNames;
import org.apache.maven.surefire.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.cli.CommandLineOption;
import org.apache.maven.surefire.extensions.ForkNodeFactory;
import org.apache.maven.surefire.providerapi.SurefireProvider;
import org.apache.maven.surefire.report.ReporterConfiguration;
import org.apache.maven.surefire.suite.RunResult;
import org.apache.maven.surefire.testset.DirectoryScannerParameters;
import org.apache.maven.surefire.testset.RunOrderParameters;
import org.apache.maven.surefire.testset.TestArtifactInfo;
import org.apache.maven.surefire.testset.TestListResolver;
import org.apache.maven.surefire.testset.TestRequest;
import org.apache.maven.surefire.testset.TestSetFailedException;
import org.apache.maven.surefire.util.DefaultScanResult;
import org.apache.maven.surefire.util.RunOrder;
import org.apache.maven.toolchain.DefaultToolchain;
import org.apache.maven.toolchain.Toolchain;
import org.apache.maven.toolchain.ToolchainManager;
import org.codehaus.plexus.logging.Logger;
import org.codehaus.plexus.languages.java.jpms.LocationManager;
import org.codehaus.plexus.languages.java.jpms.ResolvePathsRequest;
import org.codehaus.plexus.languages.java.jpms.ResolvePathsResult;

import javax.annotation.Nonnull;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.nio.file.Files;
import java.nio.file.Paths;
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.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.artifact.ArtifactUtils.artifactMapByVersionlessId;
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.suite.RunResult.failure;
import static org.apache.maven.surefire.suite.RunResult.noTestsRun;
import static org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray;
import static org.apache.maven.surefire.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();

        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 );
        }
    }

    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 )
        throws MojoExecutionException, MojoFailureException
    {
        TestClassPath testClasspath = generateTestClasspath();
        List<ProviderInfo> providers = createProviders( testClasspath );

        RunResult current = noTestsRun();

        Exception firstForkException = null;
        for ( ProviderInfo provider : providers )
        {
            try
            {
                current = current.aggregate( executeProvider( provider, scanResult, testClasspath ) );
            }
            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 TestNgProviderInfo( getTestNgArtifact() ),
                              new JUnitPlatformProviderInfo( getJunitPlatformArtifact(), testClasspath ),
                              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 )
        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() ) );

        Platform platform = PLATFORM.withJdkExecAttributesForTests( getEffectiveJvm() );
        if ( isNotForking() )
        {
            createCopyAndReplaceForkNumPlaceholder( effectiveProperties, 1 ).copyToSystemProperties();

            InPluginVMSurefireStarter surefireStarter = createInprocessStarter( provider, classLoaderConfiguration,
                    runOrderParameters, scanResult, platform, testClasspathWrapper );
            return surefireStarter.runSuitesInProcess( scanResult );
        }
        else
        {
            ForkConfiguration forkConfiguration = createForkConfiguration( platform );
            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, platform,
                                                       testClasspathWrapper );

                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()
    {
        return getModuleDescriptor().isFile();
    }

    private File getModuleDescriptor()
    {
        return new File( getClassesDirectory(), "module-info.class" );
    }

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

    /**
     * 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 Platform platform,
                                                             @Nonnull TestClassPath testClasspathWrapper )
        throws MojoExecutionException
    {
        try
        {
            Set<Artifact> providerArtifacts = provider.getProviderClasspath();
            String providerName = provider.getProviderName();
            if ( isForking && canExecuteProviderWithModularPath( platform ) )
            {
                String jvmExecutable = platform.getJdkExecAttributesForTests().getJvmExecutable();
                String javaHome = Paths.get( jvmExecutable )
                        .toAbsolutePath()
                        .normalize()
                        .getParent()
                        .getParent()
                        .toString();

                return newStartupConfigWithModularPath( classLoaderConfiguration, providerArtifacts, providerName,
                        getModuleDescriptor(), scanResult, javaHome, 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 File 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 )
                .setMainModuleDescriptor( moduleDescriptor.getAbsolutePath() );

        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 getJunitPlatformArtifact()
    {
        Artifact artifact = getProjectArtifactMap().get( "org.junit.platform:junit-platform-commons" );
        if ( artifact == null )
        {
            artifact = getPluginArtifactMap().get( "org.junit.platform:junit-platform-engine" );
        }

        Artifact projectArtifact = project.getArtifact();
        String projectGroupId = projectArtifact.getGroupId();
        if ( artifact == null && ( "org.junit.platform".equals( projectGroupId )
                || "org.junit.jupiter".equals( projectGroupId )
                || "org.junit.vintage".equals( projectGroupId ) ) )
        {
            artifact = projectArtifact;
        }

        return artifact;
    }

    private ForkStarter createForkStarter( @Nonnull ProviderInfo provider, @Nonnull ForkConfiguration forkConfiguration,
                                           @Nonnull ClassLoaderConfiguration classLoaderConfiguration,
                                           @Nonnull RunOrderParameters runOrderParameters, @Nonnull ConsoleLogger log,
                                           @Nonnull DefaultScanResult scanResult, @Nonnull Platform platform,
                                           @Nonnull TestClassPath testClasspathWrapper )
        throws MojoExecutionException, MojoFailureException
    {
        StartupConfiguration startupConfiguration = createStartupConfiguration( provider, true,
                classLoaderConfiguration, scanResult, platform, testClasspathWrapper );
        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, platform, testClasspathWrapper );
        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( Platform platform )
    {
        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 ) )
        {
            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 Integer.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( jvm ) )
        {
            File pathToJava = new File( jvm ).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() );
            BigDecimal version = jdkHome == null ? null : toJdkVersionFromReleaseFile( jdkHome );
            boolean javaVersion9 = version == null ? isJava9AtLeast( pathToJava.getPath() ) : isJava9AtLeast( version );
            return new JdkAttributes( pathToJava.getPath(), javaVersion9 );
        }

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

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

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

                return new JdkAttributes( jvmToUse, 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( getClassesDirectory() );
        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, getClassesDirectory(),
                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 = getJunitPlatformArtifact() != 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, 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> testDependencies = testClasspath.getTestDependencies();

            if ( hasDependencyPlatformEngine( testDependencies ) )
            {
                String filterTestDependency = "org.junit.platform:junit-platform-engine";
                getConsoleLogger().debug( "Test dependencies contain " + filterTestDependency );
                narrowProviderDependencies( filterTestDependency, providerArtifacts, testDependencies );
            }
            else
            {
                ProjectBuildingRequest request = getSession().getProjectBuildingRequest();
                Plugin plugin = getPluginDescriptor().getPlugin();
                Set<Artifact> engines = surefireDependencyResolver.resolvePluginDependencies( request, plugin );
                if ( hasDependencyPlatformEngine( engines ) )
                {
                    Map<String, Artifact> engineArtifacts = artifactMapByVersionlessId( engines );
                    providerArtifacts.putAll( engineArtifacts );
                    alignVersions( providerArtifacts, engineArtifacts );
                }
                else if ( hasDependencyJupiterAPI( testDependencies ) )
                {
                    String engineGroupId = "org.junit.jupiter";
                    String engineArtifactId = "junit-jupiter-engine";
                    String engineCoordinates = engineGroupId + ":" + engineArtifactId;
                    String api = "org.junit.jupiter:junit-jupiter-api";
                    getConsoleLogger().debug( "Test dependencies contain " + api + ". Resolving " + engineCoordinates );
                    String engineVersion = testDependencies.get( api ).getBaseVersion();
                    addEngineByApi( engineGroupId, engineArtifactId, engineVersion,
                            providerArtifacts, testDependencies );
                }
            }
            providerArtifacts.keySet().removeAll( testDependencies.keySet() );
            return new LinkedHashSet<>( providerArtifacts.values() );
        }

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

        private void narrowProviderDependencies( String filterTestDependency,
                                                 Map<String, Artifact> providerArtifacts,
                                                 Map<String, Artifact> testDependencies )
        {
            Artifact engine = testDependencies.get( filterTestDependency );
            String groupId = engine.getGroupId();
            String artifactId = engine.getArtifactId();
            String version = engine.getBaseVersion();
            String classifier = engine.getClassifier();
            String type = engine.getType();
            for ( Artifact engineDep : resolve( groupId, artifactId, version, classifier, type ) )
            {
                providerArtifacts.remove( engineDep.getGroupId() + ":" + engineDep.getArtifactId() );
                getConsoleLogger().debug( "Removed artifact " + engineDep
                        + " from provider. Already appears in test classpath." );
            }
            alignVersions( providerArtifacts, testDependencies );
        }

        private void alignVersions( Map<String, Artifact> providerArtifacts,
                                    Map<String, Artifact> referencedDependencies )
        {
            String version = referencedDependencies.get( "org.junit.platform:junit-platform-commons" ).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" )
                    || hasGroupArtifactId( "org.junit.jupiter", "junit-jupiter-api", getProject().getArtifact() );
        }

        private boolean hasDependencyPlatformEngine( Map<String, Artifact> dependencies )
        {
            return dependencies.containsKey( "org.junit.platform:junit-platform-engine" )
                    || hasGroupArtifactId( "org.junit.platform", "junit-platform-engine", getProject().getArtifact() );
        }

        private boolean hasDependencyPlatformEngine( Collection<Artifact> dependencies )
        {
            if ( hasGroupArtifactId( "org.junit.platform", "junit-platform-engine", getProject().getArtifact() ) )
            {
                return true;
            }

            for ( Artifact dependency : dependencies )
            {
                if ( dependency.getGroupId().equals( "org.junit.platform" )
                        && dependency.getArtifactId().equals( "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();
            return surefireDependencyResolver.resolvePluginDependencies( request, plugin );
        }
    }

    /**
     * @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() ? autoDetectOneProvider() : providersToRun;
        }

        @Nonnull private List<ProviderInfo> autoDetectOneProvider()
        {
            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;
        }
    }
}
