This is an automated email from the ASF dual-hosted git repository.

rfscholte pushed a commit to branch MJLINK-36
in repository https://gitbox.apache.org/repos/asf/maven-jlink-plugin.git

commit 9bdd41f849eaa7013b69eb62e2e7c06de5347c3a
Author: Benjamin Marwell <[email protected]>
AuthorDate: Tue Nov 17 13:27:53 2020 +0100

    Toolchain must always win. Add toolchain tests.
---
 .../MJLINK-36_toolchainjdk8/invoker.properties     |  20 ++
 src/it/projects/MJLINK-36_toolchainjdk8/pom.xml    |  95 ++++++++++
 .../MJLINK-36_toolchainjdk9/invoker.properties     |  20 ++
 src/it/projects/MJLINK-36_toolchainjdk9/pom.xml    |  95 ++++++++++
 .../maven/plugins/jlink/AbstractJLinkExecutor.java |  11 +-
 .../maven/plugins/jlink/AbstractJLinkMojo.java     |   9 +-
 .../jlink/AbstractJLinkToolchainExecutor.java      | 204 +++++++++++++++++++++
 .../apache/maven/plugins/jlink/JLinkExecutor.java  | 105 +----------
 .../org/apache/maven/plugins/jlink/JLinkMojo.java  |  32 ++--
 .../apache/maven/plugins/jlink/JLinkExecutor.java  |  37 ++--
 10 files changed, 481 insertions(+), 147 deletions(-)

diff --git a/src/it/projects/MJLINK-36_toolchainjdk8/invoker.properties 
b/src/it/projects/MJLINK-36_toolchainjdk8/invoker.properties
new file mode 100644
index 0000000..d3282c7
--- /dev/null
+++ b/src/it/projects/MJLINK-36_toolchainjdk8/invoker.properties
@@ -0,0 +1,20 @@
+# 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.
+
+invoker.java.version = 1.8
+invoker.goals = clean install
+invoker.toolchain.jdk.version = 11
diff --git a/src/it/projects/MJLINK-36_toolchainjdk8/pom.xml 
b/src/it/projects/MJLINK-36_toolchainjdk8/pom.xml
new file mode 100644
index 0000000..f6a37cd
--- /dev/null
+++ b/src/it/projects/MJLINK-36_toolchainjdk8/pom.xml
@@ -0,0 +1,95 @@
+<?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>
+  <groupId>org.apache.maven.plugins.jlink.its</groupId>
+  <artifactId>mjlink36-toolchain-jdk8</artifactId>
+  <version>1.0.0-SNAPSHOT</version>
+  <packaging>jlink</packaging>
+
+  <properties>
+    <maven.compiler.source>1.9</maven.compiler.source>
+    <maven.compiler.target>1.9</maven.compiler.target>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <!-- use a dependency with a module-info.class -->
+      <artifactId>asm</artifactId>
+      <groupId>org.ow2.asm</groupId>
+      <version>6.0</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-toolchains-plugin</artifactId>
+        <version>1.1</version>
+        <executions>
+          <execution>
+            <goals>
+              <goal>toolchain</goal>
+            </goals>
+          </execution>
+        </executions>
+        <configuration>
+          <toolchains>
+            <jdk>
+              <version>11</version>
+            </jdk>
+          </toolchains>
+        </configuration>
+      </plugin>
+
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jlink-plugin</artifactId>
+        <version>@project.version@</version>
+        <extensions>true</extensions>
+        <configuration>
+          <noHeaderFiles>true</noHeaderFiles>
+          <noManPages>true</noManPages>
+          <verbose>true</verbose>
+        </configuration>
+      </plugin>
+    </plugins>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-compiler-plugin</artifactId>
+          <version>3.8.0</version>
+          <configuration>
+            <source>${maven.compiler.source}</source>
+            <target>${maven.compiler.target}</target>
+          </configuration>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+  </build>
+
+</project>
diff --git a/src/it/projects/MJLINK-36_toolchainjdk9/invoker.properties 
b/src/it/projects/MJLINK-36_toolchainjdk9/invoker.properties
new file mode 100644
index 0000000..271bf45
--- /dev/null
+++ b/src/it/projects/MJLINK-36_toolchainjdk9/invoker.properties
@@ -0,0 +1,20 @@
+# 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.
+
+invoker.java.version = 9+
+invoker.goals = clean install
+invoker.toolchain.jdk.version = 11
diff --git a/src/it/projects/MJLINK-36_toolchainjdk9/pom.xml 
b/src/it/projects/MJLINK-36_toolchainjdk9/pom.xml
new file mode 100644
index 0000000..ab371a9
--- /dev/null
+++ b/src/it/projects/MJLINK-36_toolchainjdk9/pom.xml
@@ -0,0 +1,95 @@
+<?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>
+  <groupId>org.apache.maven.plugins.jlink.its</groupId>
+  <artifactId>mjlink36-toolchain-jdk9</artifactId>
+  <version>1.0.0-SNAPSHOT</version>
+  <packaging>jlink</packaging>
+
+  <properties>
+    <maven.compiler.source>1.9</maven.compiler.source>
+    <maven.compiler.target>1.9</maven.compiler.target>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <!-- use a dependency with a module-info.class -->
+      <artifactId>asm</artifactId>
+      <groupId>org.ow2.asm</groupId>
+      <version>6.0</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-toolchains-plugin</artifactId>
+        <version>1.1</version>
+        <executions>
+          <execution>
+            <goals>
+              <goal>toolchain</goal>
+            </goals>
+          </execution>
+        </executions>
+        <configuration>
+          <toolchains>
+            <jdk>
+              <version>11</version>
+            </jdk>
+          </toolchains>
+        </configuration>
+      </plugin>
+
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jlink-plugin</artifactId>
+        <version>@project.version@</version>
+        <extensions>true</extensions>
+        <configuration>
+          <noHeaderFiles>true</noHeaderFiles>
+          <noManPages>true</noManPages>
+          <verbose>true</verbose>
+        </configuration>
+      </plugin>
+    </plugins>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-compiler-plugin</artifactId>
+          <version>3.8.0</version>
+          <configuration>
+            <source>${maven.compiler.source}</source>
+            <target>${maven.compiler.target}</target>
+          </configuration>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+  </build>
+
+</project>
diff --git 
a/src/main/java/org/apache/maven/plugins/jlink/AbstractJLinkExecutor.java 
b/src/main/java/org/apache/maven/plugins/jlink/AbstractJLinkExecutor.java
index f6a6799..3213736 100644
--- a/src/main/java/org/apache/maven/plugins/jlink/AbstractJLinkExecutor.java
+++ b/src/main/java/org/apache/maven/plugins/jlink/AbstractJLinkExecutor.java
@@ -21,10 +21,8 @@ package org.apache.maven.plugins.jlink;
 
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugin.logging.Log;
-import org.apache.maven.toolchain.Toolchain;
 
 import java.io.File;
-import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
@@ -34,23 +32,16 @@ abstract class AbstractJLinkExecutor
 {
     protected static final String JMODS = "jmods";
 
-    private final Toolchain toolchain;
     private final Log log;
 
     private final List<String> modulesToAdd = new ArrayList<>();
     private final List<String> modulePaths = new ArrayList<>();
 
-    AbstractJLinkExecutor( Toolchain toolchain, Log log ) throws IOException
+    AbstractJLinkExecutor( Log log )
     {
-        this.toolchain = toolchain;
         this.log = log;
     }
 
-    protected Toolchain getToolchain()
-    {
-        return this.toolchain;
-    }
-
     protected Log getLog()
     {
         return this.log;
diff --git 
a/src/main/java/org/apache/maven/plugins/jlink/AbstractJLinkMojo.java 
b/src/main/java/org/apache/maven/plugins/jlink/AbstractJLinkMojo.java
index 7443b76..74bef13 100644
--- a/src/main/java/org/apache/maven/plugins/jlink/AbstractJLinkMojo.java
+++ b/src/main/java/org/apache/maven/plugins/jlink/AbstractJLinkMojo.java
@@ -20,11 +20,11 @@ package org.apache.maven.plugins.jlink;
  */
 
 import java.io.File;
-import java.io.IOException;
 import java.lang.reflect.Method;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 
 import org.apache.maven.execution.MavenSession;
 import org.apache.maven.plugin.AbstractMojo;
@@ -60,12 +60,11 @@ public abstract class AbstractJLinkMojo
     private ToolchainManager toolchainManager;
 
     protected JLinkExecutor getJlinkExecutor()
-            throws IOException
     {
-        return new JLinkExecutor( getToolchain(), getLog() );
+        return new JLinkExecutor( getToolchain().orElse( null ), getLog() );
     }
 
-    protected Toolchain getToolchain()
+    protected Optional<Toolchain> getToolchain()
     {
         Toolchain tc = null;
 
@@ -106,7 +105,7 @@ public abstract class AbstractJLinkMojo
             tc = toolchainManager.getToolchainFromBuildContext( "jdk", 
getSession() );
         }
 
-        return tc;
+        return Optional.ofNullable( tc );
     }
 
     protected MavenProject getProject()
diff --git 
a/src/main/java/org/apache/maven/plugins/jlink/AbstractJLinkToolchainExecutor.java
 
b/src/main/java/org/apache/maven/plugins/jlink/AbstractJLinkToolchainExecutor.java
new file mode 100644
index 0000000..a38a9c7
--- /dev/null
+++ 
b/src/main/java/org/apache/maven/plugins/jlink/AbstractJLinkToolchainExecutor.java
@@ -0,0 +1,204 @@
+package org.apache.maven.plugins.jlink;
+
+/*
+ * 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.commons.lang3.SystemUtils;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.logging.Log;
+import org.apache.maven.shared.utils.cli.CommandLineException;
+import org.apache.maven.shared.utils.cli.CommandLineUtils;
+import org.apache.maven.shared.utils.cli.Commandline;
+import org.apache.maven.toolchain.Toolchain;
+import org.codehaus.plexus.util.StringUtils;
+
+import java.io.File;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Optional;
+
+abstract class AbstractJLinkToolchainExecutor extends AbstractJLinkExecutor
+{
+    private final Toolchain toolchain;
+
+    AbstractJLinkToolchainExecutor( Toolchain toolchain, Log log )
+    {
+        super( log );
+        this.toolchain = toolchain;
+    }
+
+    protected Optional<Toolchain> getToolchain()
+    {
+        return Optional.ofNullable( this.toolchain );
+    }
+
+    /**
+     * Execute JLink via toolchain.
+     *
+     * @return the exit code ({@code 0} on success).
+     */
+    @Override
+    public int executeJlink( List<String> jlinkArgs ) throws 
MojoExecutionException
+    {
+        File jlinkExecutable = getJlinkExecutable();
+        getLog().info( "Toolchain in maven-jlink-plugin: jlink [ " + 
jlinkExecutable + " ]" );
+
+        Commandline cmd = createJLinkCommandLine( jlinkArgs );
+        cmd.setExecutable( jlinkExecutable.getAbsolutePath() );
+
+        return executeCommand( cmd );
+    }
+
+    private File getJlinkExecutable()
+    {
+        return new File( getJLinkExecutable() );
+    }
+
+    @Override
+    public Optional<File> getJmodsFolder( /* nullable */ File sourceJdkModules 
)
+    {
+        // Really Hacky...do we have a better solution to find the jmods 
directory of the JDK?
+        File jLinkParent = 
getJlinkExecutable().getParentFile().getParentFile();
+        File jmodsFolder;
+        if ( sourceJdkModules != null && sourceJdkModules.isDirectory() )
+        {
+            jmodsFolder = new File( sourceJdkModules, JMODS );
+        }
+        else
+        {
+            jmodsFolder = new File( jLinkParent, JMODS );
+        }
+
+        getLog().debug( " Parent: " + jLinkParent.getAbsolutePath() );
+        getLog().debug( " jmodsFolder: " + jmodsFolder.getAbsolutePath() );
+
+        return Optional.of( jmodsFolder );
+    }
+
+    private Commandline createJLinkCommandLine( List<String> jlinkArgs )
+    {
+        Commandline cmd = new Commandline();
+        jlinkArgs.forEach( arg -> cmd.createArg().setValue( arg ) );
+
+        return cmd;
+    }
+
+    private String getJLinkExecutable()
+    {
+        Optional<Toolchain> toolchain = getToolchain();
+
+        if ( !toolchain.isPresent() )
+        {
+            getLog().error( "Either JDK9+ or a toolchain "
+                    + "pointing to a JDK9+ containing a jlink binary is 
required." );
+            getLog().info( "See 
https://maven.apache.org/guides/mini/guide-using-toolchains.html "
+                    + "for mor information." );
+            throw new IllegalStateException( "Running on JDK8 and no toolchain 
found." );
+        }
+
+        String jLinkExecutable = toolchain.orElseThrow( 
NoSuchElementException::new ).findTool( "jlink" );
+
+        if ( StringUtils.isEmpty( jLinkExecutable ) )
+        {
+            throw new IllegalStateException( "The jlink executable '"
+                    + jLinkExecutable + "' doesn't exist or is not a file." );
+        }
+
+        // TODO: Check if there exist a more elegant way?
+        String jLinkCommand = "jlink" + ( SystemUtils.IS_OS_WINDOWS ? ".exe" : 
"" );
+
+        File jLinkExe = new File( jLinkExecutable );
+
+        if ( jLinkExe.isDirectory() )
+        {
+            jLinkExe = new File( jLinkExe, jLinkCommand );
+        }
+
+        if ( SystemUtils.IS_OS_WINDOWS && jLinkExe.getName().indexOf( '.' ) < 
0 )
+        {
+            jLinkExe = new File( jLinkExe.getPath() + ".exe" );
+        }
+
+        if ( !jLinkExe.isFile() )
+        {
+            throw new IllegalStateException( "The jlink executable '"
+                    + jLinkExe + "' doesn't exist or is not a file." );
+        }
+        return jLinkExe.getAbsolutePath();
+    }
+
+    private int executeCommand( Commandline cmd )
+            throws MojoExecutionException
+    {
+        if ( getLog().isDebugEnabled() )
+        {
+            // no quoted arguments ???
+            getLog().debug( CommandLineUtils.toString( cmd.getCommandline() 
).replaceAll( "'", "" ) );
+        }
+
+        CommandLineUtils.StringStreamConsumer err = new 
CommandLineUtils.StringStreamConsumer();
+        CommandLineUtils.StringStreamConsumer out = new 
CommandLineUtils.StringStreamConsumer();
+        try
+        {
+            int exitCode = CommandLineUtils.executeCommandLine( cmd, out, err 
);
+
+            String output = ( StringUtils.isEmpty( out.getOutput() ) ? null : 
'\n' + out.getOutput().trim() );
+
+            if ( exitCode != 0 )
+            {
+
+                if ( StringUtils.isNotEmpty( output ) )
+                {
+                    // Reconsider to use WARN / ERROR ?
+                    //  getLog().error( output );
+                    for ( String outputLine : output.split( "\n" ) )
+                    {
+                        getLog().error( outputLine );
+                    }
+                }
+
+                StringBuilder msg = new StringBuilder( "\nExit code: " );
+                msg.append( exitCode );
+                if ( StringUtils.isNotEmpty( err.getOutput() ) )
+                {
+                    msg.append( " - " ).append( err.getOutput() );
+                }
+                msg.append( '\n' );
+                msg.append( "Command line was: " ).append( cmd ).append( '\n' 
).append( '\n' );
+
+                throw new MojoExecutionException( msg.toString() );
+            }
+
+            if ( StringUtils.isNotEmpty( output ) )
+            {
+                //getLog().info( output );
+                for ( String outputLine : output.split( "\n" ) )
+                {
+                    getLog().info( outputLine );
+                }
+            }
+
+            return exitCode;
+        }
+        catch ( CommandLineException e )
+        {
+            throw new MojoExecutionException( "Unable to execute jlink 
command: " + e.getMessage(), e );
+        }
+    }
+}
diff --git a/src/main/java/org/apache/maven/plugins/jlink/JLinkExecutor.java 
b/src/main/java/org/apache/maven/plugins/jlink/JLinkExecutor.java
index a9299c3..7482adb 100644
--- a/src/main/java/org/apache/maven/plugins/jlink/JLinkExecutor.java
+++ b/src/main/java/org/apache/maven/plugins/jlink/JLinkExecutor.java
@@ -19,120 +19,19 @@ package org.apache.maven.plugins.jlink;
  * under the License.
  */
 
-import org.apache.commons.lang3.SystemUtils;
 import org.apache.maven.plugin.logging.Log;
 import org.apache.maven.toolchain.Toolchain;
-import org.codehaus.plexus.util.StringUtils;
-import org.codehaus.plexus.util.cli.Commandline;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.List;
-import java.util.Optional;
 
 /**
  * JDK 8-only Jlink executor.
  *
  * <p>As JDK8 does not ship jlink, a toolchain is required.</p>
  */
-class JLinkExecutor extends AbstractJLinkExecutor
+class JLinkExecutor extends AbstractJLinkToolchainExecutor
 {
-    private final String jLinkExec;
-
-    JLinkExecutor( Toolchain toolchain, Log log ) throws IOException
+    JLinkExecutor( Toolchain toolchain, Log log )
     {
         super( toolchain, log );
-        this.jLinkExec = getJLinkExecutable();
-    }
-
-    public File getJlinkExecutable()
-    {
-        return new File( this.jLinkExec );
-    }
-
-    @Override
-    public Optional<File> getJmodsFolder( /* nullable */ File sourceJdkModules 
)
-    {
-        // Really Hacky...do we have a better solution to find the jmods 
directory of the JDK?
-        File jLinkParent = 
getJlinkExecutable().getParentFile().getParentFile();
-        File jmodsFolder;
-        if ( sourceJdkModules != null && sourceJdkModules.isDirectory() )
-        {
-            jmodsFolder = new File( sourceJdkModules, JMODS );
-        }
-        else
-        {
-            jmodsFolder = new File( jLinkParent, JMODS );
-        }
-
-        getLog().debug( " Parent: " + jLinkParent.getAbsolutePath() );
-        getLog().debug( " jmodsFolder: " + jmodsFolder.getAbsolutePath() );
-
-        return Optional.of( jmodsFolder );
-    }
-
-    /**
-     * Execute JLink via any means.
-     *
-     * @return the exit code ({@code 0} on success).
-     */
-    @Override
-    public int executeJlink( List<String> jlinkArgs )
-    {
-        getLog().info( "Toolchain in maven-jlink-plugin: jlink [ " + 
this.jLinkExec + " ]" );
-
-        Commandline cmd = createJLinkCommandLine( jlinkArgs );
-        cmd.setExecutable( this.jLinkExec );
-
-        throw new UnsupportedOperationException( "not implemented" );
     }
 
-    private Commandline createJLinkCommandLine( List<String> jlinkArgs )
-    {
-        Commandline cmd = new Commandline();
-        jlinkArgs.forEach( arg -> cmd.createArg().setValue( arg ) );
-
-        return cmd;
-    }
-
-
-    protected final String getJLinkExecutable() throws IOException
-    {
-        if ( getToolchain() == null )
-        {
-            getLog().error( "Either JDK9+ or a toolchain "
-                    + "pointing to a JDK9+ containing a jlink binary is 
required." );
-            getLog().info( "See 
https://maven.apache.org/guides/mini/guide-using-toolchains.html "
-                    + "for mor information." );
-            throw new IllegalStateException( "Running on JDK8 and no toolchain 
found." );
-        }
-
-        String jLinkExecutable = getToolchain().findTool( "jlink" );
-
-        if ( StringUtils.isEmpty( jLinkExecutable ) )
-        {
-            throw new IOException( "The jlink executable '" + jLinkExecutable 
+ "' doesn't exist or is not a file." );
-        }
-
-        // TODO: Check if there exist a more elegant way?
-        String jLinkCommand = "jlink" + ( SystemUtils.IS_OS_WINDOWS ? ".exe" : 
"" );
-
-        File jLinkExe = new File( jLinkExecutable );
-
-        if ( jLinkExe.isDirectory() )
-        {
-            jLinkExe = new File( jLinkExe, jLinkCommand );
-        }
-
-        if ( SystemUtils.IS_OS_WINDOWS && jLinkExe.getName().indexOf( '.' ) < 
0 )
-        {
-            jLinkExe = new File( jLinkExe.getPath() + ".exe" );
-        }
-
-        if ( !jLinkExe.isFile() )
-        {
-            throw new IOException( "The jlink executable '" + jLinkExe + "' 
doesn't exist or is not a file." );
-        }
-        return jLinkExe.getAbsolutePath();
-    }
 }
diff --git a/src/main/java/org/apache/maven/plugins/jlink/JLinkMojo.java 
b/src/main/java/org/apache/maven/plugins/jlink/JLinkMojo.java
index c1ebfb6..3256565 100644
--- a/src/main/java/org/apache/maven/plugins/jlink/JLinkMojo.java
+++ b/src/main/java/org/apache/maven/plugins/jlink/JLinkMojo.java
@@ -28,6 +28,8 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.NoSuchElementException;
+import java.util.Optional;
 
 import org.apache.maven.artifact.Artifact;
 import org.apache.maven.plugin.MojoExecutionException;
@@ -308,7 +310,14 @@ public class JLinkMojo
 
         List<String> jlinkArgs = createJlinkArgs( pathsOfModules, modulesToAdd 
);
 
-        jLinkExec.executeJlink( jlinkArgs );
+        try
+        {
+            jLinkExec.executeJlink( jlinkArgs );
+        }
+        catch ( IllegalStateException e )
+        {
+            throw new MojoFailureException( "Unable to find jlink command: " + 
e.getMessage(), e );
+        }
 
         File createZipArchiveFromImage = createZipArchiveFromImage( 
buildDirectory, outputDirectoryImage );
 
@@ -348,10 +357,12 @@ public class JLinkMojo
 
             ResolvePathsRequest<File> request = ResolvePathsRequest.ofFiles( 
dependencyArtifacts );
 
-            Toolchain toolchain = getToolchain();
-            if ( toolchain != null && toolchain instanceof 
DefaultJavaToolChain )
+            Optional<Toolchain> toolchain = getToolchain();
+            if ( toolchain.isPresent()
+                    && toolchain.orElseThrow( NoSuchElementException::new ) 
instanceof DefaultJavaToolChain )
             {
-                request.setJdkHome( new File( ( (DefaultJavaToolChain) 
toolchain ).getJavaHome() ) );
+                Toolchain toolcahin1 = toolchain.orElseThrow( 
NoSuchElementException::new );
+                request.setJdkHome( new File( ( (DefaultJavaToolChain) 
toolcahin1 ).getJavaHome() ) );
             }
 
             ResolvePathsResult<File> resolvePathsResult = 
locationManager.resolvePaths( request );
@@ -412,18 +423,9 @@ public class JLinkMojo
         return modulepathElements;
     }
 
-    private JLinkExecutor getExecutor() throws MojoFailureException
+    private JLinkExecutor getExecutor()
     {
-        JLinkExecutor jLinkExec;
-        try
-        {
-            jLinkExec = getJlinkExecutor();
-        }
-        catch ( IOException e )
-        {
-            throw new MojoFailureException( "Unable to find jlink command: " + 
e.getMessage(), e );
-        }
-        return jLinkExec;
+        return getJlinkExecutor();
     }
 
     private boolean projectHasAlreadySetAnArtifact()
diff --git a/src/main/java9/org/apache/maven/plugins/jlink/JLinkExecutor.java 
b/src/main/java9/org/apache/maven/plugins/jlink/JLinkExecutor.java
index 7310a3e..d562816 100644
--- a/src/main/java9/org/apache/maven/plugins/jlink/JLinkExecutor.java
+++ b/src/main/java9/org/apache/maven/plugins/jlink/JLinkExecutor.java
@@ -38,9 +38,8 @@ import java.util.spi.ToolProvider;
  * <p>This implementation uses the JDK9+ Toolprovider SPI to find and execute 
jlink.
  * This way, no fork needs to be created.</p>
  */
-class JLinkExecutor extends AbstractJLinkExecutor
+class JLinkExecutor extends AbstractJLinkToolchainExecutor
 {
-
     private final ToolProvider toolProvider;
 
     JLinkExecutor( Toolchain toolchain, Log log ) throws IOException
@@ -49,18 +48,6 @@ class JLinkExecutor extends AbstractJLinkExecutor
         this.toolProvider = getJLinkExecutable();
     }
 
-    @Override
-    public Optional<File> getJmodsFolder( /* nullable */ File sourceJdkModules 
)
-    {
-        if ( sourceJdkModules != null && sourceJdkModules.isDirectory() )
-        {
-            return Optional.of( new File( sourceJdkModules, JMODS ) );
-        }
-
-        // ToolProvider does not need jmods folder to be set.
-        return Optional.empty();
-    }
-
     protected final ToolProvider getJLinkExecutable()
     {
         return ToolProvider
@@ -71,6 +58,11 @@ class JLinkExecutor extends AbstractJLinkExecutor
     @Override
     public int executeJlink( List<String> jlinkArgs ) throws 
MojoExecutionException
     {
+        if (getToolchain().isPresent())
+        {
+            return super.executeJlink( jlinkArgs );
+        }
+
         if ( getLog().isDebugEnabled() )
         {
             // no quoted arguments ???
@@ -131,4 +123,21 @@ class JLinkExecutor extends AbstractJLinkExecutor
             throw new MojoExecutionException( "Unable to execute jlink 
command: " + e.getMessage(), e );
         }
     }
+
+    @Override
+    public Optional<File> getJmodsFolder( /* nullable */ File sourceJdkModules 
)
+    {
+        if ( getToolchain().isPresent())
+        {
+            return super.getJmodsFolder( sourceJdkModules );
+        }
+
+        if ( sourceJdkModules != null && sourceJdkModules.isDirectory() )
+        {
+            return Optional.of( new File( sourceJdkModules, JMODS ) );
+        }
+
+        // ToolProvider does not need jmods folder to be set.
+        return Optional.empty();
+    }
 }

Reply via email to