Repository: maven-surefire
Updated Branches:
  refs/heads/SUREFIRE-1403 ecda11ea1 -> 395c68dc1 (forced update)


[SUREFIRE-1403] [Jigsaw] [Java 9] add "--add-modules ALL-SYSTEM" to forked CLI 
argument


Project: http://git-wip-us.apache.org/repos/asf/maven-surefire/repo
Commit: http://git-wip-us.apache.org/repos/asf/maven-surefire/commit/395c68dc
Tree: http://git-wip-us.apache.org/repos/asf/maven-surefire/tree/395c68dc
Diff: http://git-wip-us.apache.org/repos/asf/maven-surefire/diff/395c68dc

Branch: refs/heads/SUREFIRE-1403
Commit: 395c68dc117f595c119094ce30605f9dd8dc019d
Parents: 1a65d61
Author: Tibor17 <tibordig...@apache.org>
Authored: Mon Aug 7 12:43:17 2017 +0200
Committer: Tibor17 <tibordig...@apache.org>
Committed: Sat Aug 12 04:28:40 2017 +0200

----------------------------------------------------------------------
 maven-surefire-common/pom.xml                   |   2 +-
 .../plugin/surefire/AbstractSurefireMojo.java   |  72 +++++++++--
 .../maven/plugin/surefire/JdkAttributes.java    |  48 +++++++
 .../booterclient/ForkConfiguration.java         |  72 +++++++----
 .../surefire/report/StatelessXmlReporter.java   |   4 +-
 ...erDeserializerProviderConfigurationTest.java |   2 +-
 ...terDeserializerStartupConfigurationTest.java |   2 +-
 .../booterclient/ForkConfigurationTest.java     |  65 ++++++----
 pom.xml                                         |   2 +-
 surefire-api/pom.xml                            |   2 +-
 surefire-booter/pom.xml                         |   2 +-
 .../maven/surefire/booter/SystemUtils.java      | 129 ++++++++++++++++++-
 .../maven/surefire/booter/SystemUtilsTest.java  | 125 ++++++++++++++++++
 surefire-booter/src/test/resources/jdk/bin/java |   0
 .../src/test/resources/jdk/jre/bin/java         |   0
 .../src/test/resources/jdk8-IBM/release         |   1 +
 .../src/test/resources/jdk8-oracle/release      |   1 +
 .../src/test/resources/jdk9-oracle/release      |   1 +
 surefire-integration-tests/pom.xml              |   4 +-
 .../maven/surefire/its/AbstractJigsawIT.java    | 102 +++++++++++++++
 .../maven/surefire/its/Java9FullApiIT.java      |  58 +++++++++
 .../surefire/its/jiras/Surefire1265Java9IT.java |  17 ++-
 .../src/test/resources/java9-full-api/pom.xml   |  60 +++++++++
 .../java9-full-api/src/test/java/J9Test.java    |  38 ++++++
 24 files changed, 731 insertions(+), 78 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/395c68dc/maven-surefire-common/pom.xml
----------------------------------------------------------------------
diff --git a/maven-surefire-common/pom.xml b/maven-surefire-common/pom.xml
index ae050c7..121609b 100644
--- a/maven-surefire-common/pom.xml
+++ b/maven-surefire-common/pom.xml
@@ -160,7 +160,7 @@
       <plugin>
         <artifactId>maven-surefire-plugin</artifactId>
         <configuration>
-          <jvm>${test.jre}/bin/java</jvm>
+          <jvm>${jdk.home}/bin/java</jvm>
           <redirectTestOutputToFile>true</redirectTestOutputToFile>
           <includes>
             <include>**/JUnit4SuiteTest.java</include>

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/395c68dc/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
----------------------------------------------------------------------
diff --git 
a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
 
b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
index f2e5bfb..047f7a4 100644
--- 
a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
+++ 
b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
@@ -77,6 +77,7 @@ 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.surefire.util.SurefireReflectionException;
+import org.apache.maven.toolchain.DefaultToolchain;
 import org.apache.maven.toolchain.Toolchain;
 import org.apache.maven.toolchain.ToolchainManager;
 
@@ -100,13 +101,21 @@ import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
 import static java.lang.Thread.currentThread;
+import static java.util.Collections.singletonMap;
 import static org.apache.commons.lang3.JavaVersion.JAVA_1_7;
+import static org.apache.commons.lang3.JavaVersion.JAVA_9;
+import static org.apache.commons.lang3.JavaVersion.JAVA_RECENT;
 import static org.apache.commons.lang3.SystemUtils.IS_OS_WINDOWS;
 import static org.apache.commons.lang3.SystemUtils.isJavaVersionAtLeast;
 import static org.apache.maven.shared.utils.StringUtils.capitalizeFirstLetter;
 import static org.apache.maven.shared.utils.StringUtils.isEmpty;
 import static org.apache.maven.shared.utils.StringUtils.isNotBlank;
+import static org.apache.maven.shared.utils.StringUtils.isNotEmpty;
 import static org.apache.maven.shared.utils.StringUtils.split;
+import static org.apache.maven.surefire.booter.SystemUtils.endsWithJavaPath;
+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.invokeGetter;
@@ -123,6 +132,10 @@ public abstract class AbstractSurefireMojo
     extends AbstractMojo
     implements SurefireExecutionParameters
 {
+    private static final Map<String, String> JAVA_9_MATCHER_OLD_NOTATION = 
singletonMap( "version", "[1.9,)" );
+
+    private static final Map<String, String> JAVA_9_MATCHER = singletonMap( 
"version", "[9,)" );
+
     private static final Platform PLATFORM = new Platform();
 
     private static final File SYSTEM_TMP_DIR = new File( System.getProperty( 
"java.io.tmpdir" ) );
@@ -895,7 +908,7 @@ public abstract class AbstractSurefireMojo
             getConsoleLogger().info( "Toolchain in maven-" + getPluginName() + 
"-plugin: " + toolchain );
             if ( jvmToUse != null )
             {
-                getConsoleLogger().warning( "Toolchains are ignored, 
'executable' parameter is set to " + jvmToUse );
+                getConsoleLogger().warning( "Toolchains are ignored, 'jvm' 
parameter is set to " + jvmToUse );
             }
         }
 
@@ -1947,7 +1960,7 @@ public abstract class AbstractSurefireMojo
                                                     
startupReportConfiguration, consoleLogger );
     }
 
-    protected ForkConfiguration getForkConfiguration()
+    private ForkConfiguration getForkConfiguration() throws 
MojoFailureException
     {
         File tmpDir = getSurefireTempDir();
 
@@ -2038,24 +2051,59 @@ public abstract class AbstractSurefireMojo
         return debugForkedProcess;
     }
 
-    private String getEffectiveJvm()
+    private JdkAttributes getEffectiveJvm() throws MojoFailureException
     {
-        String jvmToUse = getJvm();
-        if ( toolchain != null && jvmToUse == null )
+        if ( isNotEmpty( jvm ) )
         {
-            jvmToUse = toolchain.findTool( "java" ); //NOI18N
+            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() );
+            Double version = jdkHome == null ? null : 
toJdkVersionFromReleaseFile( jdkHome );
+            boolean javaVersion9 = version == null ? isJava9AtLeast( 
pathToJava.getPath() ) : isJava9AtLeast( version );
+            return new JdkAttributes( pathToJava.getPath(), javaVersion9 );
         }
 
-        if ( isEmpty( jvmToUse ) )
+        if ( toolchain != null )
         {
-            // use the same JVM as the one used to run Maven (the "java.home" 
one)
-            jvmToUse = System.getProperty( "java.home" ) + File.separator + 
"bin" + File.separator + "java";
-            getConsoleLogger().debug( "Using JVM: " + jvmToUse );
+            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 );
+            }
         }
 
-        return jvmToUse;
-    }
+        // 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_RECENT.toString() );
 
+        return new JdkAttributes( jvmToUse, isJavaVersionAtLeast( JAVA_9 ) );
+    }
 
     private Artifact getSurefireBooterArtifact()
     {

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/395c68dc/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/JdkAttributes.java
----------------------------------------------------------------------
diff --git 
a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/JdkAttributes.java
 
b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/JdkAttributes.java
new file mode 100644
index 0000000..65b1254
--- /dev/null
+++ 
b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/JdkAttributes.java
@@ -0,0 +1,48 @@
+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 static 
org.apache.maven.surefire.util.internal.ObjectUtils.requireNonNull;
+
+/**
+ * @author <a href="mailto:tibordig...@apache.org";>Tibor Digana (tibor17)</a>
+ * @since 2.20.1
+ */
+public final class JdkAttributes
+{
+    private final String jvmExecutable;
+    private final boolean java9AtLeast;
+
+    public JdkAttributes( String jvmExecutable, boolean java9AtLeast )
+    {
+        this.jvmExecutable = requireNonNull( jvmExecutable, "null path to java 
executable" );
+        this.java9AtLeast = java9AtLeast;
+    }
+
+    public String getJvmExecutable()
+    {
+        return jvmExecutable;
+    }
+
+    public boolean isJava9AtLeast()
+    {
+        return java9AtLeast;
+    }
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/395c68dc/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkConfiguration.java
----------------------------------------------------------------------
diff --git 
a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkConfiguration.java
 
b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkConfiguration.java
index 1c7626e..b3b9251 100644
--- 
a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkConfiguration.java
+++ 
b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkConfiguration.java
@@ -20,9 +20,9 @@ package org.apache.maven.plugin.surefire.booterclient;
  */
 
 import org.apache.maven.plugin.surefire.AbstractSurefireMojo;
+import org.apache.maven.plugin.surefire.JdkAttributes;
 import 
org.apache.maven.plugin.surefire.booterclient.lazytestprovider.OutputStreamFlushableCommandline;
 import org.apache.maven.plugin.surefire.util.Relocator;
-import org.apache.maven.shared.utils.StringUtils;
 import org.apache.maven.surefire.booter.Classpath;
 import org.apache.maven.surefire.booter.ForkedBooter;
 import org.apache.maven.surefire.booter.StartupConfiguration;
@@ -42,6 +42,7 @@ import java.util.jar.JarOutputStream;
 import java.util.jar.Manifest;
 
 import static 
org.apache.maven.plugin.surefire.SurefireHelper.escapeToPlatformPath;
+import static org.apache.maven.shared.utils.StringUtils.join;
 
 /**
  * Configuration for forking tests.
@@ -66,7 +67,7 @@ public class ForkConfiguration
 
     private final Classpath bootClasspathConfiguration;
 
-    private final String jvmExecutable;
+    private final JdkAttributes jdk;
 
     private final Properties modelProperties;
 
@@ -86,14 +87,14 @@ public class ForkConfiguration
 
     @SuppressWarnings( "checkstyle:parameternumber" )
     public ForkConfiguration( Classpath bootClasspathConfiguration, File 
tmpDir, String debugLine,
-                              String jvmExecutable, File workingDirectory, 
Properties modelProperties, String argLine,
+                              JdkAttributes jdk, File workingDirectory, 
Properties modelProperties, String argLine,
                               Map<String, String> environmentVariables, 
boolean debugEnabled, int forkCount,
                               boolean reuseForks, Platform pluginPlatform )
     {
         this.bootClasspathConfiguration = bootClasspathConfiguration;
         this.tempDirectory = tmpDir;
         this.debugLine = debugLine;
-        this.jvmExecutable = jvmExecutable;
+        this.jdk = jdk;
         this.workingDirectory = workingDirectory;
         this.modelProperties = modelProperties;
         this.argLine = argLine;
@@ -131,24 +132,25 @@ public class ForkConfiguration
     }
 
     /**
-     * @param classPath            cla the classpath arguments
-     * @param startupConfiguration The startup configuration
+     * @param classPath            cli the classpath arguments
+     * @param config               The startup configuration
      * @param threadNumber         the thread number, to be the replacement in 
the argLine   @return A commandline
      * @return CommandLine able to flush entire command going to be sent to 
forked JVM
      * @throws org.apache.maven.surefire.booter.SurefireBooterForkException
      *          when unable to perform the fork
      */
-    public OutputStreamFlushableCommandline createCommandLine( List<String> 
classPath,
-                                                               
StartupConfiguration startupConfiguration,
+    public OutputStreamFlushableCommandline createCommandLine( List<String> 
classPath, StartupConfiguration config,
                                                                int 
threadNumber )
-        throws SurefireBooterForkException
+            throws SurefireBooterForkException
     {
-        return createCommandLine( classPath,
-                                  
startupConfiguration.getClassLoaderConfiguration()
-                                      .isManifestOnlyJarRequestedAndUsable(),
-                                  startupConfiguration.isShadefire(), 
startupConfiguration.isProviderMainClass()
-            ? startupConfiguration.getActualClassName()
-            : ForkedBooter.class.getName(), threadNumber );
+        boolean useJar = 
config.getClassLoaderConfiguration().isManifestOnlyJarRequestedAndUsable();
+
+        boolean shadefire = config.isShadefire();
+
+        String providerThatHasMainMethod =
+                config.isProviderMainClass() ? config.getActualClassName() : 
ForkedBooter.class.getName();
+
+        return createCommandLine( classPath, useJar, shadefire, 
providerThatHasMainMethod, threadNumber );
     }
 
     OutputStreamFlushableCommandline createCommandLine( List<String> 
classPath, boolean useJar, boolean shadefire,
@@ -157,13 +159,26 @@ public class ForkConfiguration
     {
         OutputStreamFlushableCommandline cli = new 
OutputStreamFlushableCommandline();
 
-        cli.setExecutable( jvmExecutable );
+        cli.setExecutable( jdk.getJvmExecutable() );
+
+        String jvmArgLine =
+                replaceThreadNumberPlaceholder( stripNewLines( 
replacePropertyExpressions() ), threadNumber );
+
+        if ( jdk.isJava9AtLeast() && !jvmArgLine.contains( "--add-modules" ) )
+        {
+            if ( jvmArgLine.isEmpty() )
+            {
+                jvmArgLine = "--add-modules ALL-SYSTEM";
+            }
+            else
+            {
+                jvmArgLine = "--add-modules ALL-SYSTEM " + jvmArgLine;
+            }
+        }
 
-        if ( argLine != null )
+        if ( !jvmArgLine.isEmpty() )
         {
-            cli.createArg().setLine(
-                   replaceThreadNumberPlaceholder( stripNewLines( 
replacePropertyExpressions( argLine ) ),
-                                                   threadNumber ) );
+            cli.createArg().setLine( jvmArgLine );
         }
 
         for ( Map.Entry<String, String> entry : 
environmentVariables.entrySet() )
@@ -192,7 +207,7 @@ public class ForkConfiguration
         }
         else
         {
-            cli.addEnvironment( "CLASSPATH", StringUtils.join( 
classPath.iterator(), File.pathSeparator ) );
+            cli.addEnvironment( "CLASSPATH", join( classPath.iterator(), 
File.pathSeparator ) );
 
             final String forkedBooter =
                 providerThatHasMainMethod != null ? providerThatHasMainMethod 
: ForkedBooter.class.getName();
@@ -235,11 +250,18 @@ public class ForkConfiguration
      *
      * This allows other plugins to modify or set properties with the changes 
getting picked up by surefire.
      */
-    private String replacePropertyExpressions( String argLine )
+    private String replacePropertyExpressions()
     {
         if ( argLine == null )
         {
-            return null;
+            return "";
+        }
+
+        String resolvedArgLine = argLine.trim();
+
+        if ( resolvedArgLine.isEmpty() )
+        {
+            return "";
         }
 
         for ( final String key : modelProperties.stringPropertyNames() )
@@ -247,11 +269,11 @@ public class ForkConfiguration
             String field = "@{" + key + "}";
             if ( argLine.contains( field ) )
             {
-                argLine = argLine.replace( field, modelProperties.getProperty( 
key, "" ) );
+                resolvedArgLine = resolvedArgLine.replace( field, 
modelProperties.getProperty( key, "" ) );
             }
         }
 
-        return argLine;
+        return resolvedArgLine;
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/395c68dc/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/StatelessXmlReporter.java
----------------------------------------------------------------------
diff --git 
a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/StatelessXmlReporter.java
 
b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/StatelessXmlReporter.java
index 60c6dfe..629778b 100644
--- 
a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/StatelessXmlReporter.java
+++ 
b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/StatelessXmlReporter.java
@@ -19,7 +19,6 @@ package org.apache.maven.plugin.surefire.report;
  * under the License.
  */
 
-import org.apache.maven.shared.utils.io.IOUtil;
 import org.apache.maven.shared.utils.xml.PrettyPrintXMLWriter;
 import org.apache.maven.shared.utils.xml.XMLWriter;
 import org.apache.maven.surefire.report.ReportEntry;
@@ -42,6 +41,7 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.StringTokenizer;
 
+import static org.apache.commons.io.IOUtils.closeQuietly;
 import static 
org.apache.maven.plugin.surefire.report.DefaultReporterFactory.TestResultType;
 import static 
org.apache.maven.plugin.surefire.report.FileReporterUtils.stripIllegalFilenameChars;
 import static org.apache.maven.surefire.util.internal.StringUtils.UTF_8;
@@ -239,7 +239,7 @@ public class StatelessXmlReporter
         }
         finally
         {
-            IOUtil.close( fw );
+            closeQuietly( fw );
         }
     }
 

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/395c68dc/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerProviderConfigurationTest.java
----------------------------------------------------------------------
diff --git 
a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerProviderConfigurationTest.java
 
b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerProviderConfigurationTest.java
index 5d970d8..26b8be7 100644
--- 
a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerProviderConfigurationTest.java
+++ 
b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerProviderConfigurationTest.java
@@ -207,7 +207,7 @@ public class BooterDeserializerProviderConfigurationTest
                                                  boolean readTestsFromInStream 
)
         throws IOException
     {
-        final ForkConfiguration forkConfiguration = 
ForkConfigurationTest.getForkConfiguration( null, null );
+        final ForkConfiguration forkConfiguration = 
ForkConfigurationTest.getForkConfiguration( (String) null );
         PropertiesWrapper props = new PropertiesWrapper( new HashMap<String, 
String>() );
         BooterSerializer booterSerializer = new BooterSerializer( 
forkConfiguration );
         Object test;

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/395c68dc/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java
----------------------------------------------------------------------
diff --git 
a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java
 
b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java
index 0cb292c..035add0 100644
--- 
a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java
+++ 
b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java
@@ -119,7 +119,7 @@ public class BooterDeserializerStartupConfigurationTest
     private StartupConfiguration saveAndReload( StartupConfiguration 
startupConfiguration )
         throws IOException
     {
-        final ForkConfiguration forkConfiguration = 
ForkConfigurationTest.getForkConfiguration( null, null );
+        final ForkConfiguration forkConfiguration = 
ForkConfigurationTest.getForkConfiguration( (String) null );
         PropertiesWrapper props = new PropertiesWrapper( new HashMap<String, 
String>() );
         BooterSerializer booterSerializer = new BooterSerializer( 
forkConfiguration );
         String aTest = "aTest";

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/395c68dc/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkConfigurationTest.java
----------------------------------------------------------------------
diff --git 
a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkConfigurationTest.java
 
b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkConfigurationTest.java
index 1e09d6f..b49e164 100644
--- 
a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkConfigurationTest.java
+++ 
b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkConfigurationTest.java
@@ -19,29 +19,32 @@ package org.apache.maven.plugin.surefire.booterclient;
  * under the License.
  */
 
-import java.io.File;
-import java.io.IOException;
-import java.util.Collections;
-import java.util.Properties;
-
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.lang3.RandomStringUtils;
 import org.apache.commons.lang3.SystemUtils;
+import org.apache.maven.plugin.surefire.JdkAttributes;
 import org.apache.maven.shared.utils.StringUtils;
 import org.apache.maven.shared.utils.cli.Commandline;
 import org.apache.maven.surefire.booter.Classpath;
 import org.apache.maven.surefire.booter.SurefireBooterForkException;
+import org.junit.Test;
 
-import junit.framework.TestCase;
+import java.io.File;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Properties;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 public class ForkConfigurationTest
-    extends TestCase
 {
-
+    @Test
     public void 
testCreateCommandLine_UseSystemClassLoaderForkOnce_ShouldConstructManifestOnlyJar()
         throws IOException, SurefireBooterForkException
     {
-        ForkConfiguration config = getForkConfiguration( null, "java" );
+        ForkConfiguration config = getForkConfiguration( (String) null );
         File cpElement = getTempClasspathFile();
 
         Commandline cli =
@@ -51,12 +54,13 @@ public class ForkConfigurationTest
         assertTrue( line.contains( "-jar" ) );
     }
 
+    @Test
     public void testArglineWithNewline()
         throws IOException, SurefireBooterForkException
     {
         // SUREFIRE-657
         File cpElement = getTempClasspathFile();
-        ForkConfiguration forkConfiguration = getForkConfiguration( 
"abc\ndef", null );
+        ForkConfiguration forkConfiguration = getForkConfiguration( "abc\ndef" 
);
 
         final Commandline commandLine =
             forkConfiguration.createCommandLine( Collections.singletonList( 
cpElement.getAbsolutePath() ), false, false,
@@ -64,18 +68,19 @@ public class ForkConfigurationTest
         assertTrue( commandLine.toString().contains( "abc def" ) );
     }
 
+    @Test
     public void 
testCurrentWorkingDirectoryPropagationIncludingForkNumberExpansion()
         throws IOException, SurefireBooterForkException
     {
         // SUREFIRE-1136
         File baseDir =
             new File( FileUtils.getTempDirectory(), "SUREFIRE-1136-" + 
RandomStringUtils.randomAlphabetic( 3 ) );
-        baseDir.mkdirs();
+        assertTrue( baseDir.mkdirs() );
         baseDir.deleteOnExit();
 
         File cwd = new File( baseDir, "fork_${surefire.forkNumber}" );
 
-        ForkConfiguration config = getForkConfiguration( null, "java", 
cwd.getCanonicalFile() );
+        ForkConfiguration config = getForkConfiguration( null, 
cwd.getCanonicalFile() );
         Commandline commandLine = config.createCommandLine( 
Collections.<String>emptyList(), true, false, null, 1 );
 
         File forkDirectory = new File( baseDir, "fork_1" );
@@ -84,20 +89,21 @@ public class ForkConfigurationTest
             commandLine.getShell().getWorkingDirectory().getCanonicalPath() ) 
);
     }
 
+    @Test
     public void testExceptionWhenCurrentDirectoryIsNotRealDirectory()
         throws IOException, SurefireBooterForkException
     {
         // SUREFIRE-1136
         File baseDir =
             new File( FileUtils.getTempDirectory(), "SUREFIRE-1136-" + 
RandomStringUtils.randomAlphabetic( 3 ) );
-        baseDir.mkdirs();
+        assertTrue( baseDir.mkdirs() );
         baseDir.deleteOnExit();
 
         File cwd = new File( baseDir, "cwd.txt" );
         FileUtils.touch( cwd );
         cwd.deleteOnExit();
 
-        ForkConfiguration config = getForkConfiguration( null, "java", 
cwd.getCanonicalFile() );
+        ForkConfiguration config = getForkConfiguration( null, 
cwd.getCanonicalFile() );
 
         try
         {
@@ -114,19 +120,20 @@ public class ForkConfigurationTest
         fail();
     }
 
+    @Test
     public void testExceptionWhenCurrentDirectoryCannotBeCreated()
         throws IOException, SurefireBooterForkException
     {
         // SUREFIRE-1136
         File baseDir =
             new File( FileUtils.getTempDirectory(), "SUREFIRE-1136-" + 
RandomStringUtils.randomAlphabetic( 3 ) );
-        baseDir.mkdirs();
+        assertTrue( baseDir.mkdirs() );
         baseDir.deleteOnExit();
 
         // NULL is invalid for JDK starting from 1.7.60 - 
https://github.com/openjdk-mirror/jdk/commit/e5389115f3634d25d101e2dcc71f120d4fd9f72f
         // ? character is invalid on Windows, seems to be imposable to create 
invalid directory using Java on Linux
         File cwd = new File( baseDir, "?\u0000InvalidDirectoryName" );
-        ForkConfiguration config = getForkConfiguration( null, "java", 
cwd.getAbsoluteFile() );
+        ForkConfiguration config = getForkConfiguration( null, 
cwd.getAbsoluteFile() );
 
         try
         {
@@ -152,17 +159,31 @@ public class ForkConfigurationTest
         return cpElement;
     }
 
-    public static ForkConfiguration getForkConfiguration( String argLine, 
String jvm )
+    public static ForkConfiguration getForkConfiguration( File javaExec )
+            throws IOException
+    {
+        return getForkConfiguration( null, javaExec.getAbsolutePath(), new 
File( "." ).getCanonicalFile() );
+    }
+
+    public static ForkConfiguration getForkConfiguration( String argLine )
         throws IOException
     {
-        return getForkConfiguration( argLine, jvm, new File( "." 
).getCanonicalFile() );
+        File jvm = new File( new File( System.getProperty( "java.home" ), 
"bin" ), "java" );
+        return getForkConfiguration( argLine, jvm.getAbsolutePath(), new File( 
"." ).getCanonicalFile() );
+    }
+
+    public static ForkConfiguration getForkConfiguration( String argLine, File 
cwd )
+            throws IOException
+    {
+        File jvm = new File( new File( System.getProperty( "java.home" ), 
"bin" ), "java" );
+        return getForkConfiguration( argLine, jvm.getAbsolutePath(), cwd );
     }
 
-    public static ForkConfiguration getForkConfiguration( String argLine, 
String jvm, File cwd )
+    private static ForkConfiguration getForkConfiguration( String argLine, 
String jvm, File cwd )
         throws IOException
     {
-        return new ForkConfiguration( Classpath.emptyClasspath(), null, null, 
jvm, cwd, new Properties(), argLine, null,
-                                      false, 1, false, new Platform() );
+        return new ForkConfiguration( Classpath.emptyClasspath(), null, null, 
new JdkAttributes( jvm, false ),
+                                            cwd, new Properties(), argLine, 
null, false, 1, false, new Platform() );
     }
 
     // based on 
http://stackoverflow.com/questions/2591083/getting-version-of-java-in-runtime
@@ -170,6 +191,6 @@ public class ForkConfigurationTest
     {
         String[] javaVersionElements = System.getProperty( 
"java.runtime.version" ).split( "\\.|_|-b" );
         return Integer.valueOf( javaVersionElements[1] ) >= major
-            && Integer.valueOf( javaVersionElements[4] ) >= update;
+            && Integer.valueOf( javaVersionElements[3] ) >= update;
     }
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/395c68dc/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 6ba5602..2285482 100644
--- a/pom.xml
+++ b/pom.xml
@@ -97,7 +97,7 @@
     
<maven.surefire.scm.devConnection>scm:git:https://git-wip-us.apache.org/repos/asf/maven-surefire.git</maven.surefire.scm.devConnection>
     <maven.site.path>surefire-archives/surefire-LATEST</maven.site.path>
     <!-- Override with Jigsaw JRE 9 -->
-    <test.jre>${java.home}/..</test.jre>
+    <jdk.home>${java.home}/..</jdk.home>
   </properties>
 
   <dependencyManagement>

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/395c68dc/surefire-api/pom.xml
----------------------------------------------------------------------
diff --git a/surefire-api/pom.xml b/surefire-api/pom.xml
index ec5c664..7b29c6d 100644
--- a/surefire-api/pom.xml
+++ b/surefire-api/pom.xml
@@ -52,7 +52,7 @@
       <plugin>
         <artifactId>maven-surefire-plugin</artifactId>
         <configuration>
-          <jvm>${test.jre}/bin/java</jvm>
+          <jvm>${jdk.home}/bin/java</jvm>
           <redirectTestOutputToFile>true</redirectTestOutputToFile>
           <includes>
             <include>**/JUnit4SuiteTest.java</include>

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/395c68dc/surefire-booter/pom.xml
----------------------------------------------------------------------
diff --git a/surefire-booter/pom.xml b/surefire-booter/pom.xml
index 8fdaf7e..9907424 100644
--- a/surefire-booter/pom.xml
+++ b/surefire-booter/pom.xml
@@ -85,7 +85,7 @@
           </dependency>
         </dependencies>
         <configuration>
-          <jvm>${test.jre}/bin/java</jvm>
+          <jvm>${jdk.home}/bin/java</jvm>
           <redirectTestOutputToFile>true</redirectTestOutputToFile>
           <includes>
             <include>**/JUnit4SuiteTest.java</include>

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/395c68dc/surefire-booter/src/main/java/org/apache/maven/surefire/booter/SystemUtils.java
----------------------------------------------------------------------
diff --git 
a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/SystemUtils.java
 
b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/SystemUtils.java
index ccdb6e6..cf78fc3 100644
--- 
a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/SystemUtils.java
+++ 
b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/SystemUtils.java
@@ -22,19 +22,29 @@ package org.apache.maven.surefire.booter;
 import org.apache.maven.surefire.util.ReflectionUtils;
 
 import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
 import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
 import java.lang.management.ManagementFactory;
 import java.lang.reflect.Method;
+import java.util.Properties;
+import java.util.StringTokenizer;
 
 import static java.lang.Thread.currentThread;
+import static org.apache.commons.io.IOUtils.closeQuietly;
 import static org.apache.commons.lang3.JavaVersion.JAVA_9;
 import static org.apache.commons.lang3.JavaVersion.JAVA_RECENT;
+import static org.apache.commons.lang3.StringUtils.isNumeric;
 import static org.apache.commons.lang3.SystemUtils.IS_OS_FREE_BSD;
 import static org.apache.commons.lang3.SystemUtils.IS_OS_LINUX;
 import static org.apache.commons.lang3.SystemUtils.IS_OS_NET_BSD;
 import static org.apache.commons.lang3.SystemUtils.IS_OS_OPEN_BSD;
+import static org.apache.commons.lang3.SystemUtils.isJavaVersionAtLeast;
 import static org.apache.maven.surefire.util.ReflectionUtils.invokeMethodChain;
 import static org.apache.maven.surefire.util.ReflectionUtils.tryLoadClass;
+import static 
org.apache.maven.surefire.util.internal.ObjectUtils.requireNonNull;
 
 /**
  * JDK 9 support.
@@ -44,13 +54,130 @@ import static 
org.apache.maven.surefire.util.ReflectionUtils.tryLoadClass;
  */
 public final class SystemUtils
 {
+    private static final double JIGSAW_JAVA_VERSION = 9.0d;
+
     private static final int PROC_STATUS_PID_FIRST_CHARS = 20;
 
-    public SystemUtils()
+    private SystemUtils()
     {
         throw new IllegalStateException( "no instantiable constructor" );
     }
 
+    /**
+     * @param jvmExecPath    e.g. /jdk/bin/java, /jdk/jre/bin/java
+     * @return {@code true} if {@code jvmExecPath} is path to java binary 
executor
+     */
+    public static boolean endsWithJavaPath( String jvmExecPath )
+    {
+        File javaExec = new File( jvmExecPath ).getAbsoluteFile();
+        File bin = javaExec.getParentFile();
+        String exec = javaExec.getName();
+        return exec.startsWith( "java" ) && bin != null && 
bin.getName().equals( "bin" );
+    }
+
+    /**
+     * If {@code jvmExecutable} is <tt>/jdk/bin/java</tt> or 
<tt>/jdk/jre/bin/java</tt>
+     * then the JDK home is returned <tt>/jdk</tt>. Null is returned if {@code 
jvmExecutable} is incorrect.
+     *
+     * @param jvmExecutable    /jdk/bin/java* or /jdk/jre/bin/java*
+     * @return path to jdk directory; or <tt>null</tt> if wrong path or 
directory layout of JDK installation.
+     */
+    public static File toJdkHomeFromJvmExec( String jvmExecutable )
+    {
+        File bin = new File( jvmExecutable ).getAbsoluteFile().getParentFile();
+        if ( "bin".equals( bin.getName() ) )
+        {
+            File parent = bin.getParentFile();
+            if ( "jre".equals( parent.getName() ) )
+            {
+                File jdk = parent.getParentFile();
+                return new File( jdk, "bin" ).isDirectory() ? jdk : null;
+            }
+            return parent;
+        }
+        return null;
+    }
+
+    /**
+     * If {@code jreHome} is <tt>/jdk</tt> or <tt>/jdk/jre</tt> then the JDK 
home is returned <tt>/jdk</tt>.
+     * Null is returned if {@code jreHome} is incorrect.
+     * <br>
+     * JRE home directory {@code jreHome} is typically system property 
<tt>java.home</tt>.
+     *
+     * @param jreHome    /jdk/jre
+     * @return path to JRE; or <tt>null</tt> if wrong path
+     */
+    public static File toJdkHomeFromJre( String jreHome )
+    {
+        File jre = new File( jreHome ).getAbsoluteFile();
+        return "jre".equals( jre.getName() ) ? jre.getParentFile() : null;
+    }
+
+    public static Double toJdkVersionFromReleaseFile( File jdkHome )
+    {
+        File release = new File( requireNonNull( jdkHome ).getAbsoluteFile(), 
"release" );
+        if ( !release.isFile() )
+        {
+            return null;
+        }
+        InputStream is = null;
+        try
+        {
+            Properties properties = new Properties();
+            is = new FileInputStream( release );
+            properties.load( is );
+            String javaVersion = properties.getProperty( "JAVA_VERSION" 
).replace( "\"", "" );
+            StringTokenizer versions = new StringTokenizer( javaVersion, "._" 
);
+
+            if ( versions.countTokens() == 1 )
+            {
+                javaVersion = versions.nextToken();
+            }
+            else if ( versions.countTokens() >= 2 )
+            {
+                String majorVersion = versions.nextToken();
+                String minorVersion = versions.nextToken();
+                javaVersion = isNumeric( minorVersion ) ? majorVersion + "." + 
minorVersion : majorVersion;
+            }
+            else
+            {
+                return null;
+            }
+
+            return Double.valueOf( javaVersion );
+        }
+        catch ( IOException e )
+        {
+            return null;
+        }
+        finally
+        {
+            closeQuietly( is );
+        }
+    }
+
+    public static boolean isJava9AtLeast( String jvmExecutablePath )
+    {
+        File externalJavaHome = toJdkHomeFromJvmExec( jvmExecutablePath );
+        File thisJavaHome = toJdkHomeFromJre( System.getProperty( "java.home" 
) );
+        if ( thisJavaHome.equals( externalJavaHome ) )
+        {
+            return isBuiltInJava9AtLeast();
+        }
+        Double releaseFileVersion = externalJavaHome == null ? null : 
toJdkVersionFromReleaseFile( externalJavaHome );
+        return SystemUtils.isJava9AtLeast( releaseFileVersion );
+    }
+
+    static boolean isBuiltInJava9AtLeast()
+    {
+        return isJavaVersionAtLeast( JAVA_9 );
+    }
+
+    public static boolean isJava9AtLeast( Double version )
+    {
+        return version != null && version >= JIGSAW_JAVA_VERSION;
+    }
+
     public static ClassLoader platformClassLoader()
     {
         if ( JAVA_RECENT.atLeast( JAVA_9 ) )

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/395c68dc/surefire-booter/src/test/java/org/apache/maven/surefire/booter/SystemUtilsTest.java
----------------------------------------------------------------------
diff --git 
a/surefire-booter/src/test/java/org/apache/maven/surefire/booter/SystemUtilsTest.java
 
b/surefire-booter/src/test/java/org/apache/maven/surefire/booter/SystemUtilsTest.java
index 12aff99..2b83946 100644
--- 
a/surefire-booter/src/test/java/org/apache/maven/surefire/booter/SystemUtilsTest.java
+++ 
b/surefire-booter/src/test/java/org/apache/maven/surefire/booter/SystemUtilsTest.java
@@ -21,8 +21,11 @@ package org.apache.maven.surefire.booter;
 
 import org.junit.Test;
 
+import java.io.File;
+import java.io.IOException;
 import java.lang.management.ManagementFactory;
 
+import static java.io.File.separator;
 import static org.apache.commons.lang3.JavaVersion.JAVA_9;
 import static org.apache.commons.lang3.JavaVersion.JAVA_RECENT;
 import static org.apache.commons.lang3.SystemUtils.IS_OS_FREE_BSD;
@@ -41,6 +44,128 @@ import static org.junit.Assume.assumeTrue;
 public class SystemUtilsTest
 {
     @Test
+    public void shouldParseProprietaryReleaseFile() throws IOException
+    {
+        String classes = new File( "." ).getCanonicalPath() + separator + 
"target" + separator + "test-classes";
+
+        File path = new File( classes, "jdk8-IBM" + separator + "bin" + 
separator + "java" );
+        assertThat( SystemUtils.isJava9AtLeast( path.getAbsolutePath() ) 
).isFalse();
+
+        path = new File( classes, "jdk8-oracle" + separator + "bin" + 
separator + "java" );
+        assertThat( SystemUtils.isJava9AtLeast( path.getAbsolutePath() ) 
).isFalse();
+
+        path = new File( classes, "jdk9-oracle" + separator + "bin" + 
separator + "java" );
+        assertThat( SystemUtils.isJava9AtLeast( path.getAbsolutePath() ) 
).isTrue();
+    }
+
+    @Test
+    public void shouldBeSameJdk9() throws IOException
+    {
+        testIsJava9AtLeast( new File( System.getProperty( "java.home" ) 
).getParentFile() );
+    }
+
+    @Test
+    public void shouldBeDifferentJdk9() throws IOException
+    {
+        testIsJava9AtLeast( new File( System.getProperty( "java.home" ) ) );
+    }
+
+    @Test
+    public void incorrectJdkPath() throws IOException
+    {
+        File jre = new File( System.getProperty( "java.home" ) );
+        File jdk = jre.getParentFile();
+        File incorrect = jdk.getParentFile();
+        assertThat( SystemUtils.isJava9AtLeast( incorrect.getAbsolutePath() ) 
).isFalse();
+    }
+
+    private void testIsJava9AtLeast( File pathInJdk ) throws IOException
+    {
+        File path = new File( pathInJdk, "bin" + separator + "java" );
+
+        if ( JAVA_RECENT.atLeast( JAVA_9 ) )
+        {
+            assertThat( SystemUtils.isJava9AtLeast( path.getAbsolutePath() ) 
).isTrue();
+        }
+        else
+        {
+            assertThat( SystemUtils.isJava9AtLeast( path.getAbsolutePath() ) 
).isFalse();
+        }
+
+        /*verify( config, times( 0 ) ).toJdkVersionFromReleaseFile( any( 
File.class ) );
+        verify( config, times( 1 ) ).isBuiltInJava9AtLeast();*/
+    }
+
+    @Test
+    public void shouldHaveJavaPath()
+    {
+        String javaPath = System.getProperty( "java.home" ) + separator + 
"bin" + separator + "java";
+        assertThat( SystemUtils.endsWithJavaPath( javaPath ) ).isTrue();
+    }
+
+    @Test
+    public void shouldNotHaveJavaPath()
+    {
+        assertThat( SystemUtils.endsWithJavaPath( "/jdk" ) ).isFalse();
+    }
+
+    @Test
+    public void shouldNotExtractJdkHomeFromJavaExec()
+    {
+        File pathToJdk = SystemUtils.toJdkHomeFromJvmExec( "/jdk/binx/java" );
+        assertThat( pathToJdk ).isNull();
+    }
+
+    @Test
+    public void shouldExtractJdkHomeFromJavaExec()
+    {
+        File pathToJdk = SystemUtils.toJdkHomeFromJvmExec( "/jdk/bin/java" );
+        assertThat( pathToJdk ).isEqualTo( new File( "/jdk" 
).getAbsoluteFile() );
+    }
+
+    @Test
+    public void shouldNotExtractJdkHomeFromJreExec() throws IOException
+    {
+        String classes = new File( "." ).getCanonicalPath() + separator + 
"target" + separator + "test-classes";
+        File jdk = new File( classes, "jdk" );
+        String pathToJreExec = jdk.getAbsolutePath() + separator + "jre" + 
separator + "binx" + separator + "java";
+        File pathToJdk = SystemUtils.toJdkHomeFromJvmExec( pathToJreExec );
+        assertThat( pathToJdk ).isNull();
+    }
+
+    @Test
+    public void shouldExtractJdkHomeFromJreExec() throws IOException
+    {
+        String classes = new File( "." ).getCanonicalPath() + separator + 
"target" + separator + "test-classes";
+        File jdk = new File( classes, "jdk" );
+        String pathToJreExec = jdk.getAbsolutePath() + separator + "jre" + 
separator + "bin" + separator + "java";
+        File pathToJdk = SystemUtils.toJdkHomeFromJvmExec( pathToJreExec );
+        assertThat( pathToJdk ).isEqualTo( jdk );
+    }
+
+    @Test
+    public void shouldExtractJdkHomeFromJre()
+    {
+        File pathToJdk = SystemUtils.toJdkHomeFromJre( "/jdk/jre" );
+        assertThat( pathToJdk ).isEqualTo( new File( "/jdk" 
).getAbsoluteFile() );
+    }
+
+    @Test
+    public void shouldNotExtractJdkHomeFromJre()
+    {
+        File pathToJdk = SystemUtils.toJdkHomeFromJre( "/jdk/jrex" );
+        assertThat( pathToJdk ).isNull();
+    }
+
+    @Test
+    public void shouldBeJavaVersion()
+    {
+        assertThat( SystemUtils.isJava9AtLeast( (Double) null ) ).isFalse();
+        assertThat( SystemUtils.isJava9AtLeast( 1.8d ) ).isFalse();
+        assertThat( SystemUtils.isJava9AtLeast( 9.0d ) ).isTrue();
+    }
+
+    @Test
     public void shouldBePlatformClassLoader()
     {
         ClassLoader cl = SystemUtils.platformClassLoader();

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/395c68dc/surefire-booter/src/test/resources/jdk/bin/java
----------------------------------------------------------------------
diff --git a/surefire-booter/src/test/resources/jdk/bin/java 
b/surefire-booter/src/test/resources/jdk/bin/java
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/395c68dc/surefire-booter/src/test/resources/jdk/jre/bin/java
----------------------------------------------------------------------
diff --git a/surefire-booter/src/test/resources/jdk/jre/bin/java 
b/surefire-booter/src/test/resources/jdk/jre/bin/java
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/395c68dc/surefire-booter/src/test/resources/jdk8-IBM/release
----------------------------------------------------------------------
diff --git a/surefire-booter/src/test/resources/jdk8-IBM/release 
b/surefire-booter/src/test/resources/jdk8-IBM/release
new file mode 100644
index 0000000..f8baa30
--- /dev/null
+++ b/surefire-booter/src/test/resources/jdk8-IBM/release
@@ -0,0 +1 @@
+JAVA_VERSION="1.8.0"

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/395c68dc/surefire-booter/src/test/resources/jdk8-oracle/release
----------------------------------------------------------------------
diff --git a/surefire-booter/src/test/resources/jdk8-oracle/release 
b/surefire-booter/src/test/resources/jdk8-oracle/release
new file mode 100644
index 0000000..567277b
--- /dev/null
+++ b/surefire-booter/src/test/resources/jdk8-oracle/release
@@ -0,0 +1 @@
+JAVA_VERSION="1.8.0_141"

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/395c68dc/surefire-booter/src/test/resources/jdk9-oracle/release
----------------------------------------------------------------------
diff --git a/surefire-booter/src/test/resources/jdk9-oracle/release 
b/surefire-booter/src/test/resources/jdk9-oracle/release
new file mode 100644
index 0000000..afcc747
--- /dev/null
+++ b/surefire-booter/src/test/resources/jdk9-oracle/release
@@ -0,0 +1 @@
+JAVA_VERSION="9"

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/395c68dc/surefire-integration-tests/pom.xml
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/pom.xml 
b/surefire-integration-tests/pom.xml
index d9142de..fee00c4 100644
--- a/surefire-integration-tests/pom.xml
+++ b/surefire-integration-tests/pom.xml
@@ -100,7 +100,8 @@
           <forkMode>never</forkMode>
           <argLine>${argLine}</argLine>
           <includes>
-            <include>org/apache/**/*IT*.java</include>
+            <include>org/apache/**/Java9FullApiIT.java</include>
+            <include>org/apache/**/Surefire1265Java9IT.java</include>
           </includes>
           <!-- Pass current surefire version to the main suite so that it -->
           <!-- can forward to all integration test projects. SUREFIRE-513 -->
@@ -115,6 +116,7 @@
             
<useInterpolatedSettings>${useInterpolatedSettings}</useInterpolatedSettings>
             
<testBuildDirectory>${project.build.testOutputDirectory}</testBuildDirectory>
             <verifier.forkMode>${verifier.forkMode}</verifier.forkMode>
+            <jdk.home>${jdk.home}</jdk.home>
           </systemPropertyVariables>
           <redirectTestOutputToFile>false</redirectTestOutputToFile>
         </configuration>

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/395c68dc/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/AbstractJigsawIT.java
----------------------------------------------------------------------
diff --git 
a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/AbstractJigsawIT.java
 
b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/AbstractJigsawIT.java
new file mode 100644
index 0000000..5d95a8d
--- /dev/null
+++ 
b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/AbstractJigsawIT.java
@@ -0,0 +1,102 @@
+package org.apache.maven.surefire.its;
+
+/*
+ * 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.surefire.its.fixture.SurefireJUnit4IntegrationTestCase;
+import org.apache.maven.surefire.its.fixture.SurefireLauncher;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+import java.util.StringTokenizer;
+
+import static org.apache.commons.lang3.JavaVersion.JAVA_9;
+import static org.apache.commons.lang3.JavaVersion.JAVA_RECENT;
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
+
+/**
+ * Abstract test class for Jigsaw tests.
+ *
+ * @author <a href="mailto:tibordig...@apache.org";>Tibor Digana (tibor17)</a>
+ * @since 2.20.1
+ */
+public abstract class AbstractJigsawIT
+        extends SurefireJUnit4IntegrationTestCase
+{
+    private static final String JDK_HOME_KEY = "jdk.home";
+    private static final String JDK_HOME = System.getProperty( JDK_HOME_KEY );
+    private static final double JIGSAW_JAVA_VERSION = 9.0d;
+
+    protected abstract String getProjectDirectoryName();
+
+    protected SurefireLauncher assumeJigsaw() throws IOException
+    {
+        assumeTrue( "There's no JDK 9 provided.",
+                          JAVA_RECENT.atLeast( JAVA_9 ) || JDK_HOME != null && 
isExtJava9AtLeast() );
+        // fail( JDK_HOME_KEY + " was provided with value " + JDK_HOME + " but 
it is not Jigsaw Java 9." );
+
+        SurefireLauncher launcher = unpack( getProjectDirectoryName() );
+
+        if ( JDK_HOME != null )
+        {
+            launcher.setLauncherJavaHome( JDK_HOME );
+        }
+
+        return launcher;
+    }
+
+    private static boolean isExtJava9AtLeast() throws IOException
+    {
+        File release = new File( JDK_HOME, "release" );
+
+        if ( !release.isFile() )
+        {
+            fail( JDK_HOME_KEY + " was provided with value " + JDK_HOME + " 
but file does not exist "
+                          + JDK_HOME + File.separator + "release"
+            );
+        }
+
+        Properties properties = new Properties();
+        try ( InputStream is = new FileInputStream( release ) )
+        {
+            properties.load( is );
+        }
+        String javaVersion = properties.getProperty( "JAVA_VERSION" ).replace( 
"\"", "" );
+        StringTokenizer versions = new StringTokenizer( javaVersion, "._" );
+
+        if ( versions.countTokens() == 1 )
+        {
+            javaVersion = versions.nextToken();
+        }
+        else if ( versions.countTokens() >= 2 )
+        {
+            javaVersion = versions.nextToken() + "." + versions.nextToken();
+        }
+        else
+        {
+            fail( "unexpected java version format" );
+        }
+
+        return Double.valueOf( javaVersion ) >= JIGSAW_JAVA_VERSION;
+    }
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/395c68dc/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/Java9FullApiIT.java
----------------------------------------------------------------------
diff --git 
a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/Java9FullApiIT.java
 
b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/Java9FullApiIT.java
new file mode 100644
index 0000000..9ebd2f3
--- /dev/null
+++ 
b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/Java9FullApiIT.java
@@ -0,0 +1,58 @@
+package org.apache.maven.surefire.its;
+
+/*
+ * 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.surefire.its.fixture.OutputValidator;
+import org.junit.Test;
+
+import java.io.IOException;
+
+/**
+ * Running Surefire on the top of JDK 9 and should be able to load
+ * classes of multiple different Jigsaw modules without error.
+ *
+ * @author <a href="mailto:tibordig...@apache.org";>Tibor Digana (tibor17)</a>
+ * @since 2.20.1
+ */
+public class Java9FullApiIT
+        extends AbstractJigsawIT
+{
+
+    @Test
+    public void shouldLoadMultipleJavaModules() throws IOException
+    {
+        OutputValidator validator = assumeJigsaw()
+                                            .setForkJvm()
+                                            .executeTest()
+                                            .verifyErrorFree( 2 );
+
+        validator.verifyTextInLog( "loaded class java.sql.SQLException" )
+                .verifyTextInLog( "loaded class javax.xml.ws.Holder" )
+                .verifyTextInLog( "loaded class javax.xml.bind.JAXBException" )
+                .verifyTextInLog( "loaded class org.omg.CORBA.BAD_INV_ORDER" )
+                .verifyTextInLog( "java.specification.version=9" );
+    }
+
+    @Override
+    protected String getProjectDirectoryName()
+    {
+        return "java9-full-api";
+    }
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/395c68dc/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1265Java9IT.java
----------------------------------------------------------------------
diff --git 
a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1265Java9IT.java
 
b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1265Java9IT.java
index 9e06e8e..2e92805 100644
--- 
a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1265Java9IT.java
+++ 
b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1265Java9IT.java
@@ -19,11 +19,10 @@ package org.apache.maven.surefire.its.jiras;
  * under the License.
  */
 
-import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase;
-import org.apache.maven.surefire.its.fixture.SurefireLauncher;
+import org.apache.maven.surefire.its.AbstractJigsawIT;
 import org.junit.Test;
 
-import static org.junit.Assume.assumeTrue;
+import java.io.IOException;
 
 @SuppressWarnings( { "javadoc", "checkstyle:javadoctype" } )
 /**
@@ -40,19 +39,19 @@ import static org.junit.Assume.assumeTrue;
  * @since 2.20.1
  */
 public class Surefire1265Java9IT
-        extends SurefireJUnit4IntegrationTestCase
+        extends AbstractJigsawIT
 {
     @Test
-    public void shouldRunInPluginJava9()
+    public void shouldRunInPluginJava9() throws IOException
     {
-        assumeTrue( System.getProperty( "java.specification.version" 
).compareTo( "1.8" ) > 0 );
-        unpack()
+        assumeJigsaw()
                 .executeTest()
                 .verifyErrorFree( 2 );
     }
 
-    private SurefireLauncher unpack()
+    @Override
+    protected String getProjectDirectoryName()
     {
-        return unpack( "/surefire-1265" );
+        return "/surefire-1265";
     }
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/395c68dc/surefire-integration-tests/src/test/resources/java9-full-api/pom.xml
----------------------------------------------------------------------
diff --git 
a/surefire-integration-tests/src/test/resources/java9-full-api/pom.xml 
b/surefire-integration-tests/src/test/resources/java9-full-api/pom.xml
new file mode 100644
index 0000000..099900c
--- /dev/null
+++ b/surefire-integration-tests/src/test/resources/java9-full-api/pom.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0";
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.maven.surefire</groupId>
+        <artifactId>it-parent</artifactId>
+        <version>1.0</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>java9-full-api</artifactId>
+
+    <properties>
+        <maven.compiler.source>1.6</maven.compiler.source>
+        <maven.compiler.target>1.6</maven.compiler.target>
+    </properties>
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <forkMode>once</forkMode>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <dependencies>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.12</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+</project>

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/395c68dc/surefire-integration-tests/src/test/resources/java9-full-api/src/test/java/J9Test.java
----------------------------------------------------------------------
diff --git 
a/surefire-integration-tests/src/test/resources/java9-full-api/src/test/java/J9Test.java
 
b/surefire-integration-tests/src/test/resources/java9-full-api/src/test/java/J9Test.java
new file mode 100644
index 0000000..0ee3115
--- /dev/null
+++ 
b/surefire-integration-tests/src/test/resources/java9-full-api/src/test/java/J9Test.java
@@ -0,0 +1,38 @@
+/*
+ * 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.junit.Test;
+
+public class J9Test
+{
+    @Test
+    public void testMiscellaneousAPI() throws java.sql.SQLException
+    {
+        System.out.println( "loaded class " + 
java.sql.SQLException.class.getName() );
+        System.out.println( "loaded class " + 
javax.xml.ws.Holder.class.getName() );
+        System.out.println( "loaded class " + 
javax.xml.bind.JAXBException.class.getName() );
+        System.out.println( "loaded class " + 
org.omg.CORBA.BAD_INV_ORDER.class.getName() );
+        System.out.println( "java.specification.version=" + 
System.getProperty( "java.specification.version" ) );
+    }
+
+    @Test
+    public void test_corba_mod() throws org.omg.CORBA.BAD_INV_ORDER
+    {
+    }
+}

Reply via email to