Bug 563530 - [9] -Xbootclasspath/a should still be supported

Change-Id: Ibcd1691f233a4e991d21f81fb33f528b8425947d
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java
index 389144d..10086fb 100644
--- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java
@@ -232,9 +232,7 @@
 		addTest(new TestSuite(ClasspathContainerTests.class));
 		addTest(new TestSuite(RuntimeClasspathEntryTests.class));
 		addTest(new TestSuite(ClasspathProviderTests.class));
-		if (!JavaProjectHelper.isJava9Compatible()) {
-			addTest(new TestSuite(BootpathTests.class));
-		}
+		addTest(new TestSuite(BootpathTests.class));
 		addTest(new TestSuite(EEDefinitionTests.class));
 		if (JavaProjectHelper.isJava9Compatible()) {
 			addTest(new TestSuite(ModuleOptionsTests.class));
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/core/BootpathTests.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/core/BootpathTests.java
index c0a6137..ed29561 100644
--- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/core/BootpathTests.java
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/core/BootpathTests.java
@@ -21,6 +21,8 @@
 import org.eclipse.core.runtime.Path;
 import org.eclipse.debug.core.ILaunchConfiguration;
 import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.debug.testplugin.JavaProjectHelper;
 import org.eclipse.jdt.debug.tests.AbstractDebugTest;
 import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
 import org.eclipse.jdt.launching.IRuntimeClasspathEntry;
@@ -32,12 +34,22 @@
  */
 public class BootpathTests extends AbstractDebugTest {
 
+	String mainClass;
+	boolean isJava9Compatible;
+
 	public BootpathTests(String name) {
 		super(name);
+		this.isJava9Compatible = JavaProjectHelper.isJava9Compatible();
+		this.mainClass = this.isJava9Compatible ? "LogicalStructures" : "Breakpoints";
+	}
+
+	@Override
+	protected IJavaProject getProjectContext() {
+		return this.isJava9Compatible ? get9Project() : super.getProjectContext();
 	}
 
 	public void testDefaultBootpath() throws Exception {
-		ILaunchConfiguration config = getLaunchConfiguration("Breakpoints");
+		ILaunchConfiguration config = getLaunchConfiguration(this.mainClass);
 
 		JavaLaunchDelegate delegate = new JavaLaunchDelegate();
 		String[] path = delegate.getBootpath(config);
@@ -51,15 +63,20 @@
 	}
 
 	public void testEmptyBootpath() throws Exception {
-		ILaunchConfiguration config = getLaunchConfiguration("Breakpoints");
+		ILaunchConfiguration config = getLaunchConfiguration(this.mainClass);
 		ILaunchConfigurationWorkingCopy wc = config.getWorkingCopy();
 
 		wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_DEFAULT_CLASSPATH, false);
 
 		JavaLaunchDelegate delegate = new JavaLaunchDelegate();
 		String[] path = delegate.getBootpath(wc);
-		assertNotNull("Empty bootpath should be empty array", path);
-		assertEquals("bootpath should be empty", 0, path.length);
+		if (this.isJava9Compatible) {
+			// strange difference between versions
+			assertNull("Empty bootpath should be null", path);
+		} else {
+			assertNotNull("Empty bootpath should be empty array", path);
+			assertEquals("bootpath should be empty", 0, path.length);
+		}
 		String[][] pathInfo= delegate.getBootpathExt(config);
 		assertNotNull("Bootpath info should'nt be null", pathInfo);
 		assertEquals("Wrong bootpath info array size",3, pathInfo.length);
@@ -69,7 +86,7 @@
 	}
 
 	public void testPrependBootpath() throws Exception {
-		ILaunchConfiguration config = getLaunchConfiguration("Breakpoints");
+		ILaunchConfiguration config = getLaunchConfiguration(this.mainClass);
 		ILaunchConfigurationWorkingCopy wc = config.getWorkingCopy();
 		IRuntimeClasspathEntry[] classpath = JavaRuntime.computeUnresolvedRuntimeClasspath(wc);
 		IRuntimeClasspathEntry[] newpath = new IRuntimeClasspathEntry[classpath.length + 1];
@@ -91,9 +108,39 @@
 		Map<String, Object> map = delegate.getVMSpecificAttributesMap(wc);
 		assertNotNull("Missing VM specific attributes map", map);
 		String[] prepath = (String[]) map.get(IJavaLaunchConfigurationConstants.ATTR_BOOTPATH_PREPEND);
-		assertNotNull("Missing bootpath prepend", pre);
+		assertNotNull("Missing bootpath prepend", prepath);
 		assertEquals("Incorrect number of prepends", 1, prepath.length);
 		assertEquals("wrong prepended path", jar.getLocation().toOSString(), prepath[0]);
 	}
 
+	public void testAppendBootpathJava() throws Exception {
+		IJavaProject project = getProjectContext();
+
+		IResource jar = get14Project().getProject().getFile(new Path("src/A.jar"));
+
+		List<String> mementos = new ArrayList<>(3);
+		mementos.add(JavaRuntime.newDefaultProjectClasspathEntry(project).getMemento());
+		if (this.isJava9Compatible) {
+			mementos.add(JavaRuntime.computeModularJREEntry(project).getMemento());
+		} else {
+			mementos.add(JavaRuntime.computeJREEntry(project).getMemento());
+		}
+		IRuntimeClasspathEntry jarEntry = JavaRuntime.newArchiveRuntimeClasspathEntry(jar.getFullPath());
+		jarEntry.setClasspathProperty(IRuntimeClasspathEntry.BOOTSTRAP_CLASSES);
+		mementos.add(jarEntry.getMemento());
+
+		ILaunchConfiguration config = getLaunchConfiguration(project, this.mainClass);
+		ILaunchConfigurationWorkingCopy wc = config.getWorkingCopy();
+		wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_DEFAULT_CLASSPATH, false);
+		wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_CLASSPATH, mementos);
+
+		JavaLaunchDelegate delegate = new JavaLaunchDelegate();
+		Map<String, Object> map = delegate.getVMSpecificAttributesMap(wc);
+		assertNotNull("Missing VM specific attributes map", map);
+		String[] postpath = (String[]) map.get(IJavaLaunchConfigurationConstants.ATTR_BOOTPATH_APPEND);
+		assertNotNull("Missing bootpath append", postpath);
+		assertEquals("Incorrect number of appends", 1, postpath.length);
+		assertEquals("wrong appended path", jar.getLocation().toOSString(), postpath[0]);
+	}
+
 }
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/AbstractJavaLaunchConfigurationDelegate.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/AbstractJavaLaunchConfigurationDelegate.java
index 82e7b1b..90b2b98 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/AbstractJavaLaunchConfigurationDelegate.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/AbstractJavaLaunchConfigurationDelegate.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2019 IBM Corporation and others.
+ * Copyright (c) 2000, 2020 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -322,13 +322,10 @@
 		IRuntimeClasspathEntry jreEntry = null;
 		while (jreEntry == null && index < entries.length) {
 			IRuntimeClasspathEntry entry = entries[index++];
-			if (entry.getClasspathProperty() == IRuntimeClasspathEntry.BOOTSTRAP_CLASSES
-					|| entry.getClasspathProperty() == IRuntimeClasspathEntry.STANDARD_CLASSES) {
-				if (JavaRuntime.isVMInstallReference(entry)) {
-					jreEntry = entry;
-				} else {
-					bootEntriesPrepend.add(entry);
-				}
+			if (JavaRuntime.isVMInstallReference(entry)) {
+				jreEntry = entry;
+			} else if (entry.getClasspathProperty() == IRuntimeClasspathEntry.BOOTSTRAP_CLASSES) {
+				bootEntriesPrepend.add(entry);
 			}
 		}
 		IRuntimeClasspathEntry[] bootEntriesPrep = JavaRuntime