[574268] Tomcat Run-Configuration gets destroyed
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatServerBehaviour.java b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatServerBehaviour.java
index 500af23..4faacb3 100644
--- a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatServerBehaviour.java
+++ b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatServerBehaviour.java
@@ -52,12 +52,6 @@
 		"-Dcom.sun.management.jmxremote.ssl=",
 		"-Dcom.sun.management.jmxremote.authenticate="
 	};
-	private static final String[] ALLOW_REFLECTION_ARGS = new String[] {
-				"--add-opens=java.base/java.lang=ALL-UNNAMED",
-				"--add-opens=java.base/java.io=ALL-UNNAMED",
-				"--add-opens=java.base/java.util=ALL-UNNAMED",
-				"--add-opens=java.base/java.util.concurrent=ALL-UNNAMED",
-				"--add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED"};
 
 	// the thread used to ping the server to check for startup
 	protected transient PingThread ping = null;
@@ -664,7 +658,8 @@
 	 * to be the last argument in the merged string.
 	 * 
 	 * @param originalArg String of original arguments.
-	 * @param vmArgs Arguments to merge into the original arguments string
+	 * @param vmArgs Arguments to merge into the original arguments string, <b>array
+	 * elements will be nulled</b>
 	 * @param excludeArgs Arguments to exclude from the original arguments string
 	 * @param keepActionLast If <b>true</b> the vmArguments are assumed to be Tomcat
 	 * program arguments, the last of which is the action to perform which must
@@ -697,6 +692,10 @@
 					vmArgs[i] = null;
 				}
 			} else if (ind2 >= 0) { // a=b style
+				//* Check for two '=' variant, e.g. --add-opens=java.base/java.lang=ALL-UNNAMED */
+				if (ind2 >= 0 && ind2 < vmArgs[i].length() && vmArgs[i].indexOf("=", ind2 + 1) > 0) {
+					ind2 = vmArgs[i].indexOf("=", ind2 + 1);
+				}
 				int index = originalArg.indexOf(vmArgs[i].substring(0, ind2 + 1));
 				if (index == 0 || (index > 0 && Character.isWhitespace(originalArg.charAt(index - 1)))) {
 					// replace
@@ -962,7 +961,7 @@
 					}
 				}
 				if (version != null && version_num >= 9) {
-					mergedVMArguments = mergeArguments(mergedVMArguments, ALLOW_REFLECTION_ARGS, null, false);
+					mergedVMArguments = mergeArguments(mergedVMArguments, getAllowReflectionArguments(), null, false);
 					workingCopy.setAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS, mergedVMArguments);
 				}
 			}
@@ -1139,6 +1138,15 @@
 		return getTomcatServer().getServerDeployDirectory();
 	}
 	
+	public static String[] getAllowReflectionArguments() {
+		return new String[] {
+			"--add-opens=java.base/java.lang=ALL-UNNAMED",
+			"--add-opens=java.base/java.io=ALL-UNNAMED",
+			"--add-opens=java.base/java.util=ALL-UNNAMED",
+			"--add-opens=java.base/java.util.concurrent=ALL-UNNAMED",
+			"--add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED"};
+	}
+
 	/**
 	 * Gets the directory to which to deploy a module's web application.
 	 * 
diff --git a/tests/org.eclipse.jst.server.tomcat.core.tests/META-INF/MANIFEST.MF b/tests/org.eclipse.jst.server.tomcat.core.tests/META-INF/MANIFEST.MF
index 61505f3..3ba09a5 100644
--- a/tests/org.eclipse.jst.server.tomcat.core.tests/META-INF/MANIFEST.MF
+++ b/tests/org.eclipse.jst.server.tomcat.core.tests/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: org.eclipse.jst.server.tomcat.core.tests
 Bundle-SymbolicName: org.eclipse.jst.server.tomcat.core.tests
-Bundle-Version: 1.1.500.qualifier
+Bundle-Version: 1.1.600.qualifier
 Bundle-ClassPath: tests.jar
 Bundle-Activator: org.eclipse.jst.server.tomcat.core.tests.TestsPlugin
 Bundle-Vendor: Eclipse.org
@@ -26,5 +26,6 @@
  org.eclipse.jst.server.core,
  org.eclipse.debug.ui,
  org.eclipse.wst.web
+Import-Package: javax.servlet
 Eclipse-LazyStart: true
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
diff --git a/tests/org.eclipse.jst.server.tomcat.core.tests/pom.xml b/tests/org.eclipse.jst.server.tomcat.core.tests/pom.xml
index cc3727d..eef4540 100644
--- a/tests/org.eclipse.jst.server.tomcat.core.tests/pom.xml
+++ b/tests/org.eclipse.jst.server.tomcat.core.tests/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>

 <!--

-  Copyright (c) 2012, 2018 Eclipse Foundation and others.

+  Copyright (c) 2012, 2021 Eclipse Foundation and others.

   All rights reserved. This program and the accompanying materials

   are made available under the terms of the Eclipse Distribution License v1.0

   which accompanies this distribution, and is available at

@@ -22,7 +22,7 @@
 

   <groupId>org.eclipse.webtools.servertools</groupId>

   <artifactId>org.eclipse.jst.server.tomcat.core.tests</artifactId>

-  <version>1.1.500-SNAPSHOT</version>

+  <version>1.1.600-SNAPSHOT</version>

   <packaging>eclipse-test-plugin</packaging>

 

   <properties>

diff --git a/tests/org.eclipse.jst.server.tomcat.core.tests/src/org/eclipse/jst/server/tomcat/core/tests/internal/UtilTestCase.java b/tests/org.eclipse.jst.server.tomcat.core.tests/src/org/eclipse/jst/server/tomcat/core/tests/internal/UtilTestCase.java
index 3fa28d5..c75aff3 100644
--- a/tests/org.eclipse.jst.server.tomcat.core.tests/src/org/eclipse/jst/server/tomcat/core/tests/internal/UtilTestCase.java
+++ b/tests/org.eclipse.jst.server.tomcat.core.tests/src/org/eclipse/jst/server/tomcat/core/tests/internal/UtilTestCase.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2013 IBM Corporation and others.
+ * Copyright (c) 2004, 2021 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
  * which accompanies this distribution, and is available at
@@ -13,8 +13,12 @@
 package org.eclipse.jst.server.tomcat.core.tests.internal;
 
 import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.Properties;
 
 import org.eclipse.core.runtime.IStatus;
+import org.eclipse.debug.core.DebugPlugin;
 import org.eclipse.jst.server.tomcat.core.internal.TomcatServerBehaviour;
 import org.eclipse.jst.server.tomcat.core.internal.VerifyResourceSpec;
 import org.eclipse.jst.server.tomcat.core.tests.RuntimeLocation;
@@ -167,4 +171,26 @@
 			assertFalse(status.isOK());
 		}
 	}
+
+	public void testArgParsing() {
+		String[] parsedArguments = DebugPlugin.parseArguments(String.join(" ", TomcatServerBehaviour.getAllowReflectionArguments()));
+		for (int i = 0; i < parsedArguments.length; i++) {
+			assertEquals(TomcatServerBehaviour.getAllowReflectionArguments()[i], parsedArguments[i]);
+		}
+	}
+
+	public void testBug574268() throws IOException {
+		Properties props = new Properties();
+		props.load(new InputStreamReader(getClass().getResourceAsStream("UtilTestCase.properties"), "utf8"));
+		// irrevocably strips the quotes from the argument values
+		String[] before = DebugPlugin.parseArguments(props.getProperty("before"));
+		String mergedVMArguments = TomcatServerBehaviour.mergeArguments(String.join(" ", before), TomcatServerBehaviour.getAllowReflectionArguments(), null, false);
+		for (int i = 0; i < before.length; i++) {
+			assertTrue("missing " + before[i], mergedVMArguments.contains(before[i]));
+		}
+		for (int i = 0; i < TomcatServerBehaviour.getAllowReflectionArguments().length; i++) {
+			assertTrue("missing " + TomcatServerBehaviour.getAllowReflectionArguments()[i], mergedVMArguments.contains(TomcatServerBehaviour.getAllowReflectionArguments()[i]));
+		}
+		assertFalse("still broken", mergedVMArguments.equals(props.get("after")));
+	}
 }
diff --git a/tests/org.eclipse.jst.server.tomcat.core.tests/src/org/eclipse/jst/server/tomcat/core/tests/internal/UtilTestCase.properties b/tests/org.eclipse.jst.server.tomcat.core.tests/src/org/eclipse/jst/server/tomcat/core/tests/internal/UtilTestCase.properties
new file mode 100644
index 0000000..9a845e1
--- /dev/null
+++ b/tests/org.eclipse.jst.server.tomcat.core.tests/src/org/eclipse/jst/server/tomcat/core/tests/internal/UtilTestCase.properties
@@ -0,0 +1,2 @@
+before=-Dcatalina.base="Q:\\source\\.metadata\\.plugins\\org.eclipse.wst.server.core\\tmp1" -Dcatalina.home="C:\\Program Files\\Tomcat" -Dwtp.deploy="Q:\\source\\.metadata\\.plugins\\org.eclipse.wst.server.core\\tmp1\\wtpwebapps" --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED -Djava.library.path="C:\\Program Files\\Tomcat\\bin" -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -ea
+after=-Dcatalina.base="Q:\\source\\.metadata\\.plugins\\org.eclipse.wst.server.core\\tmp1" -Dcatalina.home="C:\\Program Files\\Tomcat" -Dwtp.deploy="Q:\\source\\.metadata\\.plugins\\org.eclipse.wst.server.core\\tmp1\\wtpwebapps" --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED -Djava.library.path="C:\\Program Files\\Tomcat\\bin" -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -ea