Bug 544469 - Search Installed JREs is listing too many JREs

Change-Id: I46e87f6f2311399c4915cfa594e985af4225c0fa
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/InstalledJREsBlock.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/InstalledJREsBlock.java
index 237764f..ad1c819 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/InstalledJREsBlock.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/InstalledJREsBlock.java
@@ -961,35 +961,6 @@
 			return;
 		}
 
-
-		if (monitor.isCanceled()) {
-			return;
-		}
-		try {
-			monitor.subTask(NLS.bind(JREMessages.InstalledJREsBlock_14, new String[] { Integer.toString(found.size()),
-					directory.getCanonicalPath().replaceAll("&", "&&") })); // @see bug 29855 //$NON-NLS-1$ //$NON-NLS-2$
-		} catch (IOException e) {
-		}
-		IVMInstallType[] vmTypes = JavaRuntime.getVMInstallTypes();
-		if (!ignore.contains(directory)) {
-			// Take the first VM install type that claims the location as a
-			// valid VM install. VM install types should be smart enough to not
-			// claim another type's VM, but just in case...
-			for (int j = 0; j < vmTypes.length; j++) {
-				if (monitor.isCanceled()) {
-					return;
-				}
-				IVMInstallType type = vmTypes[j];
-				IStatus status = type.validateInstallLocation(directory);
-				if (status.isOK()) {
-					found.add(directory);
-					types.add(type);
-					break;
-				}
-			}
-		}
-
-		// Finding all sub directories
 		String[] names = directory.list();
 		if (names == null) {
 			return;
@@ -999,9 +970,44 @@
 			if (monitor.isCanceled()) {
 				return;
 			}
-			File dir = new File(directory, names[i]);
-			if (dir.isDirectory()) {
-				subDirs.add(dir);
+			File file = new File(directory, names[i]);
+			try {
+				monitor.subTask(NLS.bind(JREMessages.InstalledJREsBlock_14, new String[]{Integer.toString(found.size()),
+						file.getCanonicalPath().replaceAll("&", "&&")}));   // @see bug 29855 //$NON-NLS-1$ //$NON-NLS-2$
+			} catch (IOException e) {
+			}
+			IVMInstallType[] vmTypes = JavaRuntime.getVMInstallTypes();
+			if (file.isDirectory()) {
+				if (!ignore.contains(file)) {
+					boolean validLocation = false;
+
+					// Take the first VM install type that claims the location as a
+					// valid VM install.  VM install types should be smart enough to not
+					// claim another type's VM, but just in case...
+					for (int j = 0; j < vmTypes.length; j++) {
+						if (monitor.isCanceled()) {
+							return;
+						}
+						IVMInstallType type = vmTypes[j];
+						IStatus status = type.validateInstallLocation(file);
+						if (status.isOK()) {
+							String filePath = file.getPath();
+							int index = filePath.lastIndexOf(File.separatorChar);
+							File newFile = file;
+							// remove bin folder from install location as java executables are found only under bin for Java 9 and above
+							if (index > 0 && filePath.substring(index + 1).equals("bin")) { //$NON-NLS-1$
+								newFile = new File(filePath.substring(0, index));
+							}
+							found.add(newFile);
+							types.add(type);
+							validLocation = true;
+							break;
+						}
+					}
+					if (!validLocation) {
+						subDirs.add(file);
+					}
+				}
 			}
 		}
 		while (!subDirs.isEmpty()) {
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVMType.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVMType.java
index 69a21ba..ea5d9ef 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVMType.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVMType.java
@@ -132,7 +132,9 @@
 	 * VM install locations, relative to the VM install location. From Java 9 onwards, there may not be a jre directory.
 	 */
 	private static final String[] fgCandidateJavaFiles = {"javaw", "javaw.exe", "java", "java.exe", "j9w", "j9w.exe", "j9", "j9.exe"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
-	private static final String[] fgCandidateJavaLocations = { "bin" + File.separatorChar, JRE + File.separatorChar + "bin" + File.separatorChar };//$NON-NLS-1$ //$NON-NLS-2$
+	private static final String[] fgCandidateJavaLocations = { File.separator, "bin" + File.separatorChar, //$NON-NLS-1$
+			JRE + File.separatorChar + "bin" + File.separatorChar };//$NON-NLS-1$
+
 	private static ILibraryLocationResolver[] fgLibraryLocationResolvers = null;
 
 	/**
@@ -145,8 +147,19 @@
 	public static File findJavaExecutable(File vmInstallLocation) {
 		// Try each candidate in order.  The first one found wins.  Thus, the order
 		// of fgCandidateJavaLocations and fgCandidateJavaFiles is significant.
+
+		boolean isBin = false;
+		String filePath = vmInstallLocation.getPath();
+		int index = filePath.lastIndexOf(File.separatorChar);
+		if (index > 0 && filePath.substring(index + 1).equals("bin")) { //$NON-NLS-1$
+			isBin = true;
+		}
 		for (int i = 0; i < fgCandidateJavaFiles.length; i++) {
 			for (int j = 0; j < fgCandidateJavaLocations.length; j++) {
+				if (!isBin && j == 0) {
+					// search in "." only under bin for java executables for Java 9 and above
+					continue;
+				}
 				File javaFile = new File(vmInstallLocation, fgCandidateJavaLocations[j] + fgCandidateJavaFiles[i]);
 				if (javaFile.isFile()) {
 					return javaFile;
@@ -643,7 +656,9 @@
 		if (javaExecutable == null) {
 			status = new Status(IStatus.ERROR, LaunchingPlugin.getUniqueIdentifier(), 0, LaunchingMessages.StandardVMType_Not_a_JDK_Root__Java_executable_was_not_found_1, null); //
 		} else {
-			if (canDetectDefaultSystemLibraries(javaHome, javaExecutable)) {
+			File javaHomeNew = javaHome;
+
+			if (canDetectDefaultSystemLibraries(javaHomeNew, javaExecutable)) {
 				status = new Status(IStatus.OK, LaunchingPlugin.getUniqueIdentifier(), 0, LaunchingMessages.StandardVMType_ok_2, null);
 			} else {
 				status = new Status(IStatus.ERROR, LaunchingPlugin.getUniqueIdentifier(), 0, LaunchingMessages.StandardVMType_Not_a_JDK_root__System_library_was_not_found__1, null);