Repository: quarkusio/quarkus
Issue: native-image location

**Describe the bug**
io.quarkus:quarkus-maven-plugin:0.18.0:native-image 

expects the native-image to be located in: /Java/JavaVirtualMachines/graalvm-ce-19.0.2/bin/native-image

The actual location is:  /graalvm-ce-19.0.2/Contents/Home/bin

**Expected behavior**

After `gu install native-image` quarkus should pick-up the native-image without any additional configuration.

**Actual behavior**
Image is not found


**To Reproduce**
Steps to reproduce the behavior:
1. Install GraalVM 19.0.2
2. Run `gu install native-image`
3. Run `mvn io.quarkus:quarkus-maven-plugin:0.18.0:create`
4. Run `mvn clean install -Pnative


**Environment (please complete the following information):**

18.6.0 Darwin Kernel Version 18.6.0: Thu Apr 25 23:16:27 PDT 2019; root:xnu-4903.261.4~2/RELEASE_X86_64 x86_64

openjdk version "1.8.0_212"
OpenJDK Runtime Environment (build 1.8.0_212-20190523183630.graal2.jdk8u-src-tar-gz-b03)
OpenJDK 64-Bit GraalVM CE 19.0.2 (build 25.212-b03-jvmci-19-b04, mixed mode)

Quarkus version: 18.0.0

Changed files:
core/creator/src/main/java/io/quarkus/creator/phase/nativeimage/NativeImagePhase.java
devtools/maven/src/main/java/io/quarkus/maven/NativeImageMojo.java

diff --git a/core/creator/src/main/java/io/quarkus/creator/phase/nativeimage/NativeImagePhase.java b/core/creator/src/main/java/io/quarkus/creator/phase/nativeimage/NativeImagePhase.java
index 0c1efe0a0c0..3cfb2c681fb 100644
--- a/core/creator/src/main/java/io/quarkus/creator/phase/nativeimage/NativeImagePhase.java
+++ b/core/creator/src/main/java/io/quarkus/creator/phase/nativeimage/NativeImagePhase.java
@@ -15,6 +15,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import java.util.Properties;
 import java.util.concurrent.CountDownLatch;
 import java.util.stream.Collectors;
@@ -44,11 +45,26 @@ public class NativeImagePhase implements AppCreationPhase<NativeImagePhase>, Nat
 
     private static final String GRAALVM_HOME = "GRAALVM_HOME";
 
+    /**
+     * Name of the <em>system</em> property to retrieve JAVA_HOME
+     */
+    private static final String JAVA_HOME_SYS = "java.home";
+
+    /**
+     * Name of the <em>environment</em> variable to retrieve JAVA_HOME
+     */
+    private static final String JAVA_HOME_ENV = "JAVA_HOME";
+
     private static final String QUARKUS_PREFIX = "quarkus.";
 
     private static final boolean IS_LINUX = System.getProperty("os.name").toLowerCase(Locale.ROOT).contains("linux");
     private static final boolean IS_WINDOWS = System.getProperty("os.name").toLowerCase(Locale.ROOT).contains("windows");
 
+    /**
+     * The name of the environment variable containing the system path.
+     */
+    private static final String PATH = "PATH";
+
     private Path outputDir;
 
     private boolean reportErrorsAtRuntime;
@@ -75,6 +91,8 @@ public class NativeImagePhase implements AppCreationPhase<NativeImagePhase>, Nat
 
     private String graalvmHome;
 
+    private File javaHome;
+
     private boolean enableServer;
 
     private boolean enableJni;
@@ -173,6 +191,11 @@ public NativeImagePhase setGraalvmHome(String graalvmHome) {
         return this;
     }
 
+    public NativeImagePhase setJavaHome(File javaHome) {
+        this.javaHome = javaHome;
+        return this;
+    }
+
     public NativeImagePhase setEnableServer(boolean enableServer) {
         this.enableServer = enableServer;
         return this;
@@ -327,21 +350,27 @@ public void provideOutcome(AppCreator ctx) throws AppCreatorException {
                 noPIE = detectNoPIE();
             }
 
-            String graalvmHome = this.graalvmHome;
-            if (graalvmHome != null) {
-                env.put(GRAALVM_HOME, graalvmHome);
+            String graal = this.graalvmHome;
+            File java = this.javaHome;
+            if (graal != null) {
+                env.put(GRAALVM_HOME, graal);
             } else {
-                graalvmHome = env.get(GRAALVM_HOME);
-                if (graalvmHome == null) {
-                    throw new AppCreatorException("GRAALVM_HOME was not set");
+                graal = env.get(GRAALVM_HOME);
+            }
+            if (java == null) {
+                // try system property first - it will be the JAVA_HOME used by the current JVM
+                String home = System.getProperty(JAVA_HOME_SYS);
+                if (home == null) {
+                    // No luck, somewhat a odd JVM not enforcing this property
+                    // try with the JAVA_HOME environment variable
+                    home = env.get(JAVA_HOME_ENV);
+                }
+
+                if (home != null) {
+                    java = new File(home);
                 }
             }
-            String imageName = IS_WINDOWS ? "native-image.cmd" : "native-image";
-            nativeImage = Collections.singletonList(graalvmHome + File.separator + "bin" + File.separator + imageName);
-            if (Files.notExists(Paths.get(nativeImage.get(0)))) {
-                throw new AppCreatorException("The `native-image` tool (" + nativeImage.get(0)
-                        + ") is not installed, this can be done by running `gu install native-image`");
-            }
+            nativeImage = Collections.singletonList(getNativeImageExecutable(graal, java, env).getAbsolutePath());
         }
 
         try {
@@ -530,6 +559,43 @@ private boolean isThisGraalVMRCObsolete() {
         return false;
     }
 
+    private static File getNativeImageExecutable(String graalVmHome, File javaHome, Map<String, String> env)
+            throws AppCreatorException {
+        String imageName = IS_WINDOWS ? "native-image.cmd" : "native-image";
+        if (graalVmHome != null) {
+            File file = Paths.get(graalVmHome, "bin", imageName).toFile();
+            if (file.exists()) {
+                return file;
+            }
+        }
+
+        if (javaHome != null) {
+            File file = new File(javaHome, "bin/" + imageName);
+            if (file.exists()) {
+                return file;
+            }
+        }
+
+        // System path
+        String systemPath = env.get(PATH);
+        if (systemPath != null) {
+            String[] pathDirs = systemPath.split(File.pathSeparator);
+            for (String pathDir : pathDirs) {
+                File dir = new File(pathDir);
+                if (dir.isDirectory()) {
+                    File file = new File(dir, imageName);
+                    if (file.exists()) {
+                        return file;
+                    }
+                }
+            }
+        }
+
+        throw new AppCreatorException("Cannot find the `" + imageName + "` in the GRAALVM_HOME, JAVA_HOME and System " +
+                "PATH. Install it using `gu install native-image`");
+
+    }
+
     private static String getLinuxID(String option) {
         Process process;
 
diff --git a/devtools/maven/src/main/java/io/quarkus/maven/NativeImageMojo.java b/devtools/maven/src/main/java/io/quarkus/maven/NativeImageMojo.java
index 0a24f4820b7..f22224014c6 100644
--- a/devtools/maven/src/main/java/io/quarkus/maven/NativeImageMojo.java
+++ b/devtools/maven/src/main/java/io/quarkus/maven/NativeImageMojo.java
@@ -46,6 +46,9 @@ public class NativeImageMojo extends AbstractMojo {
     @Parameter(defaultValue = "${project}", readonly = true, required = true)
     protected MavenProject project;
 
+    @Parameter(defaultValue = "${java.home}", required = true, readonly = true)
+    public File javaHome;
+
     @Parameter(defaultValue = "${project.build.directory}")
     private File buildDir;
 
@@ -355,6 +358,7 @@ public Path getOriginalJar() {
                 .setEnableVMInspection(enableVMInspection)
                 .setFullStackTraces(fullStackTraces)
                 .setGraalvmHome(graalvmHome)
+                .setJavaHome(javaHome)
                 .setNativeImageXmx(nativeImageXmx)
                 .setReportErrorsAtRuntime(reportErrorsAtRuntime)
                 .setReportExceptionStackTraces(reportExceptionStackTraces));