[494936] Add Tomcat 8.5 support to WTP Server Tools to Neon.

Includes some cleanup for other versions. Include version bumps for 3.8
maintenance. 

Change-Id: If079c7a0e8d2b0ab0cefba39c8c86110fc974282
diff --git a/features/org.eclipse.jst.server_adapters.ext.feature/feature.xml b/features/org.eclipse.jst.server_adapters.ext.feature/feature.xml
index 6b2e9bc..d19a52a 100644
--- a/features/org.eclipse.jst.server_adapters.ext.feature/feature.xml
+++ b/features/org.eclipse.jst.server_adapters.ext.feature/feature.xml
@@ -2,7 +2,7 @@
 <feature

       id="org.eclipse.jst.server_adapters.ext.feature"

       label="%featureName"

-      version="3.3.500.qualifier"

+      version="3.3.501.qualifier"

       provider-name="%providerName"

       license-feature="org.eclipse.license"

       license-feature-version="1.0.1.qualifier">

diff --git a/features/org.eclipse.jst.server_adapters.ext.feature/pom.xml b/features/org.eclipse.jst.server_adapters.ext.feature/pom.xml
index e955537..8c9ea85 100644
--- a/features/org.eclipse.jst.server_adapters.ext.feature/pom.xml
+++ b/features/org.eclipse.jst.server_adapters.ext.feature/pom.xml
@@ -22,7 +22,7 @@
 

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

   <artifactId>org.eclipse.jst.server_adapters.ext.feature</artifactId>

-  <version>3.3.500-SNAPSHOT</version>

+  <version>3.3.501-SNAPSHOT</version>

   <packaging>eclipse-feature</packaging>

 

   <build>

diff --git a/features/org.eclipse.jst.server_adapters.ext.sdk.feature/feature.xml b/features/org.eclipse.jst.server_adapters.ext.sdk.feature/feature.xml
index 4f0169a..797473e 100644
--- a/features/org.eclipse.jst.server_adapters.ext.sdk.feature/feature.xml
+++ b/features/org.eclipse.jst.server_adapters.ext.sdk.feature/feature.xml
@@ -2,7 +2,7 @@
 <feature

       id="org.eclipse.jst.server_adapters.ext.sdk.feature"

       label="%featureName"

-      version="3.3.500.qualifier"

+      version="3.3.501.qualifier"

       provider-name="%providerName"

       license-feature="org.eclipse.license"

       license-feature-version="1.0.1.qualifier">

diff --git a/features/org.eclipse.jst.server_adapters.ext.sdk.feature/pom.xml b/features/org.eclipse.jst.server_adapters.ext.sdk.feature/pom.xml
index 680884f..b633036 100644
--- a/features/org.eclipse.jst.server_adapters.ext.sdk.feature/pom.xml
+++ b/features/org.eclipse.jst.server_adapters.ext.sdk.feature/pom.xml
@@ -22,6 +22,6 @@
 

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

   <artifactId>org.eclipse.jst.server_adapters.ext.sdk.feature</artifactId>

-  <version>3.3.500-SNAPSHOT</version>

+  <version>3.3.501-SNAPSHOT</version>

   <packaging>eclipse-feature</packaging>

 </project>

diff --git a/plugins/org.eclipse.jst.server.tomcat.core/META-INF/MANIFEST.MF b/plugins/org.eclipse.jst.server.tomcat.core/META-INF/MANIFEST.MF
index 8679564..951af42 100644
--- a/plugins/org.eclipse.jst.server.tomcat.core/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.jst.server.tomcat.core/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.jst.server.tomcat.core; singleton:=true
-Bundle-Version: 1.1.800.qualifier
+Bundle-Version: 1.1.801.qualifier
 Bundle-Activator: org.eclipse.jst.server.tomcat.core.internal.TomcatPlugin
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/plugin.properties b/plugins/org.eclipse.jst.server.tomcat.core/plugin.properties
index 6417b0e..f20c5a4 100644
--- a/plugins/org.eclipse.jst.server.tomcat.core/plugin.properties
+++ b/plugins/org.eclipse.jst.server.tomcat.core/plugin.properties
@@ -29,6 +29,8 @@
 runtimeTypeTomcat70Description=Apache Tomcat v7.0 supports J2EE 1.2, 1.3, 1.4, and Java EE 5 and 6 Web modules.
 runtimeTypeTomcat80Label=Apache Tomcat v8.0
 runtimeTypeTomcat80Description=Apache Tomcat v8.0 supports J2EE 1.2, 1.3, 1.4, and Java EE 5, 6, and 7 Web modules.
+runtimeTypeTomcat85Label=Apache Tomcat v8.5
+runtimeTypeTomcat85Description=Apache Tomcat v8.5 supports J2EE 1.2, 1.3, 1.4, and Java EE 5, 6, and 7 Web modules.
 runtimeTypeTomcat90Label=Apache Tomcat v9.0
 runtimeTypeTomcat90Description=Apache Tomcat v9.0 supports J2EE 1.2, 1.3, 1.4, and Java EE 5, 6, 7, and 8 Web modules.
 
@@ -57,6 +59,9 @@
 tomcat80ServerType=Tomcat v8.0 Server
 tomcat80ServerDescription=Publishes and runs J2EE and Java EE Web projects and server configurations to a local Tomcat server.
 
+tomcat85ServerType=Tomcat v8.5 Server
+tomcat85ServerDescription=Publishes and runs J2EE and Java EE Web projects and server configurations to a local Tomcat server.
+
 tomcat90ServerType=Tomcat v9.0 Server
 tomcat90ServerDescription=Publishes and runs J2EE and Java EE Web projects and server configurations to a local Tomcat server.
 
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/plugin.xml b/plugins/org.eclipse.jst.server.tomcat.core/plugin.xml
index 466ba16..1ee3d67 100644
--- a/plugins/org.eclipse.jst.server.tomcat.core/plugin.xml
+++ b/plugins/org.eclipse.jst.server.tomcat.core/plugin.xml
@@ -122,6 +122,20 @@
          versions="1.0"/>
     </runtimeType>
     <runtimeType
+       id="org.eclipse.jst.server.tomcat.runtime.85"
+       name="%runtimeTypeTomcat85Label"
+       description="%runtimeTypeTomcat85Description"
+       vendor="%apache"
+       version="8.5"
+       class="org.eclipse.jst.server.tomcat.core.internal.TomcatRuntime">
+       <moduleType
+         types="jst.web"
+         versions="2.2, 2.3, 2.4, 2.5, 3.0, 3.1"/>
+       <moduleType
+         types="jst.utility"
+         versions="1.0"/>
+    </runtimeType>
+    <runtimeType
        id="org.eclipse.jst.server.tomcat.runtime.90"
        name="%runtimeTypeTomcat90Label"
        description="%runtimeTypeTomcat90Description"
@@ -273,6 +287,21 @@
        behaviourClass="org.eclipse.jst.server.tomcat.core.internal.TomcatServerBehaviour">
      </serverType>
      <serverType
+       id="org.eclipse.jst.server.tomcat.85"
+       name="%tomcat85ServerType"
+       description="%tomcat85ServerDescription"
+       supportsRemoteHosts="false"
+       runtime="true"
+       startTimeout="45000"
+       stopTimeout="15000"
+       initialState="stopped"
+       hasConfiguration="true"
+       launchConfigId="org.eclipse.jst.server.tomcat.core.launchConfigurationType"
+       runtimeTypeId="org.eclipse.jst.server.tomcat.runtime.85"
+       class="org.eclipse.jst.server.tomcat.core.internal.TomcatServer"
+       behaviourClass="org.eclipse.jst.server.tomcat.core.internal.TomcatServerBehaviour">
+     </serverType>
+     <serverType
        id="org.eclipse.jst.server.tomcat.90"
        name="%tomcat90ServerType"
        description="%tomcat90ServerDescription"
@@ -364,6 +393,10 @@
 
     <runtime-component-version
        type="org.eclipse.jst.server.tomcat"
+       version="8.5"/>
+
+    <runtime-component-version
+       type="org.eclipse.jst.server.tomcat"
        version="9.0"/>
 
     <adapter>
@@ -480,6 +513,21 @@
     <supported>
       <runtime-component
          id="org.eclipse.jst.server.tomcat"
+         version="8.5"/>
+      <facet
+         id="jst.web"
+         version="2.2,2.3,2.4,2.5,3.0,3.1"/>
+      <facet
+         id="jst.webfragment"
+         version="3.0,3.1"/>
+      <facet
+         id="jst.utility"
+         version="1.0"/>
+    </supported>
+
+    <supported>
+      <runtime-component
+         id="org.eclipse.jst.server.tomcat"
          version="9.0"/>
       <facet
          id="jst.web"
@@ -534,6 +582,10 @@
       runtime-component="org.eclipse.jst.server.tomcat"
       version="8.0"/>
     <runtimeFacetMapping
+      runtimeTypeId="org.eclipse.jst.server.tomcat.runtime.85"
+      runtime-component="org.eclipse.jst.server.tomcat"
+      version="8.5"/>
+    <runtimeFacetMapping
       runtimeTypeId="org.eclipse.jst.server.tomcat.runtime.90"
       runtime-component="org.eclipse.jst.server.tomcat"
       version="9.0"/>
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/pom.xml b/plugins/org.eclipse.jst.server.tomcat.core/pom.xml
index 84deef1..5111ce2 100644
--- a/plugins/org.eclipse.jst.server.tomcat.core/pom.xml
+++ b/plugins/org.eclipse.jst.server.tomcat.core/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  Copyright (c) 2012, 2013 Eclipse Foundation and others.
+  Copyright (c) 2012, 2016 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,6 +22,6 @@
 
   <groupId>org.eclipse.webtools.servertools</groupId>
   <artifactId>org.eclipse.jst.server.tomcat.core</artifactId>
-  <version>1.1.800-SNAPSHOT</version>
+  <version>1.1.801-SNAPSHOT</version>
   <packaging>eclipse-plugin</packaging>
 </project>
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Messages.java b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Messages.java
index 52c0eae..f3fffa2 100644
--- a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Messages.java
+++ b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Messages.java
@@ -32,6 +32,7 @@
 	public static String errorJRETomcat60;
 	public static String errorJRETomcat70;
 	public static String errorJRETomcat80;
+	public static String errorJRETomcat85;
 	public static String errorJRETomcat90;
 	public static String warningJRE;
 	public static String warningCantReadConfig;
@@ -56,6 +57,7 @@
 	public static String errorSpec60;
 	public static String errorSpec70;
 	public static String errorSpec80;
+	public static String errorSpec85;
 	public static String errorSpec90;
 	public static String portServer;
 	public static String runtimeDirPrepared;
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Messages.properties b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Messages.properties
index 14ef566..014b5a9 100644
--- a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Messages.properties
+++ b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Messages.properties
@@ -70,6 +70,7 @@
 errorJRETomcat60=Tomcat version 6.0 requires J2SE 5.0 or later.  Change the JRE to one that meets this requirement.
 errorJRETomcat70=Tomcat version 7.0 requires Java SE 6 or later.  Change the JRE to one that meets this requirement.
 errorJRETomcat80=Tomcat version 8.0 requires Java SE 7 or later.  Change the JRE to one that meets this requirement.
+errorJRETomcat85=Tomcat version 8.5 requires Java SE 7 or later.  Change the JRE to one that meets this requirement.
 errorJRETomcat90=Tomcat version 9.0 requires Java SE 8 or later.  Change the JRE to one that meets this requirement.
 errorPortInvalid=The server cannot be started because one or more of the ports are invalid. Open the server editor and correct the invalid ports.
 errorPortInUse=Port {0} required by {1} is already in use. The server may already be running in another process, or a system process may be using the port. \
@@ -95,6 +96,7 @@
 errorSpec60=Tomcat version 6.0 only supports J2EE 1.2, 1.3, 1.4, and Java EE 5 Web modules
 errorSpec70=Tomcat version 7.0 only supports J2EE 1.2, 1.3, 1.4, and Java EE 5 and 6 Web modules
 errorSpec80=Tomcat version 8.0 only supports J2EE 1.2, 1.3, 1.4, and Java EE 5, 6, and 7 Web modules
+errorSpec85=Tomcat version 8.5 only supports J2EE 1.2, 1.3, 1.4, and Java EE 5, 6, and 7 Web modules
 errorSpec90=Tomcat version 9.0 only supports J2EE 1.2, 1.3, 1.4, and Java EE 5, 6, 7, and 8 Web modules
 errorDuplicateContextRoot=Two or more Web modules defined in the configuration have the same context root ({0}). \
   To start this server you will need to remove the duplicate(s).
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat60Configuration.java b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat60Configuration.java
index 098a4e7..856832e 100644
--- a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat60Configuration.java
+++ b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat60Configuration.java
@@ -279,7 +279,7 @@
 				return;
 			monitor.done();
 		} catch (Exception e) {
-			Trace.trace(Trace.WARNING, "Could not load Tomcat v5.5 configuration from " + path.toOSString() + ": " + e.getMessage());
+			Trace.trace(Trace.WARNING, "Could not load Tomcat v6.0 configuration from " + path.toOSString() + ": " + e.getMessage());
 			throw new CoreException(new Status(IStatus.ERROR, TomcatPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorCouldNotLoadConfiguration, path.toOSString()), e));
 		}
 	}
@@ -363,7 +363,7 @@
 				throw new Exception("Cancelled");
 			monitor.done();
 		} catch (Exception e) {
-			Trace.trace(Trace.WARNING, "Could not reload Tomcat v5.5 configuration from: " + folder.getFullPath() + ": " + e.getMessage());
+			Trace.trace(Trace.WARNING, "Could not reload Tomcat v6.0 configuration from: " + folder.getFullPath() + ": " + e.getMessage());
 			throw new CoreException(new Status(IStatus.ERROR, TomcatPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorCouldNotLoadConfiguration, folder.getFullPath().toOSString()), e));
 		}
 	}
@@ -422,7 +422,7 @@
 				return;
 			monitor.done();
 		} catch (Exception e) {
-			Trace.trace(Trace.SEVERE, "Could not save Tomcat v5.5 configuration to " + path, e);
+			Trace.trace(Trace.SEVERE, "Could not save Tomcat v6.0 configuration to " + path, e);
 			throw new CoreException(new Status(IStatus.ERROR, TomcatPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorCouldNotSaveConfiguration, new String[] {e.getLocalizedMessage()}), e));
 		}
 	}
@@ -514,7 +514,7 @@
 				return;
 			monitor.done();
 		} catch (Exception e) {
-			Trace.trace(Trace.SEVERE, "Could not save Tomcat v5.5 configuration to " + folder.toString(), e);
+			Trace.trace(Trace.SEVERE, "Could not save Tomcat v6.0 configuration to " + folder.toString(), e);
 			throw new CoreException(new Status(IStatus.ERROR, TomcatPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorCouldNotSaveConfiguration, new String[] {e.getLocalizedMessage()}), e));
 		}
 	}
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat70Configuration.java b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat70Configuration.java
index dc37b1d..d20ff67 100644
--- a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat70Configuration.java
+++ b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat70Configuration.java
@@ -279,7 +279,7 @@
 				return;
 			monitor.done();
 		} catch (Exception e) {
-			Trace.trace(Trace.WARNING, "Could not load Tomcat v5.5 configuration from " + path.toOSString() + ": " + e.getMessage());
+			Trace.trace(Trace.WARNING, "Could not load Tomcat v7.0 configuration from " + path.toOSString() + ": " + e.getMessage());
 			throw new CoreException(new Status(IStatus.ERROR, TomcatPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorCouldNotLoadConfiguration, path.toOSString()), e));
 		}
 	}
@@ -363,7 +363,7 @@
 				throw new Exception("Cancelled");
 			monitor.done();
 		} catch (Exception e) {
-			Trace.trace(Trace.WARNING, "Could not reload Tomcat v5.5 configuration from: " + folder.getFullPath() + ": " + e.getMessage());
+			Trace.trace(Trace.WARNING, "Could not reload Tomcat v7.0 configuration from: " + folder.getFullPath() + ": " + e.getMessage());
 			throw new CoreException(new Status(IStatus.ERROR, TomcatPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorCouldNotLoadConfiguration, folder.getFullPath().toOSString()), e));
 		}
 	}
@@ -422,7 +422,7 @@
 				return;
 			monitor.done();
 		} catch (Exception e) {
-			Trace.trace(Trace.SEVERE, "Could not save Tomcat v5.5 configuration to " + path, e);
+			Trace.trace(Trace.SEVERE, "Could not save Tomcat v7.0 configuration to " + path, e);
 			throw new CoreException(new Status(IStatus.ERROR, TomcatPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorCouldNotSaveConfiguration, new String[] {e.getLocalizedMessage()}), e));
 		}
 	}
@@ -514,7 +514,7 @@
 				return;
 			monitor.done();
 		} catch (Exception e) {
-			Trace.trace(Trace.SEVERE, "Could not save Tomcat v5.5 configuration to " + folder.toString(), e);
+			Trace.trace(Trace.SEVERE, "Could not save Tomcat v7.0 configuration to " + folder.toString(), e);
 			throw new CoreException(new Status(IStatus.ERROR, TomcatPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorCouldNotSaveConfiguration, new String[] {e.getLocalizedMessage()}), e));
 		}
 	}
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat80Configuration.java b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat80Configuration.java
index 49f0fd7..462b558 100644
--- a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat80Configuration.java
+++ b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat80Configuration.java
@@ -72,7 +72,7 @@
 	}
 	
 	/**
-	 * Tomcat60Configuration constructor.
+	 * Tomcat80Configuration constructor.
 	 * 
 	 * @param path a path
 	 */
@@ -240,7 +240,7 @@
 			monitor = ProgressUtil.getMonitorFor(monitor);
 			monitor.beginTask(Messages.loadingTask, 7);
 			
-			// check for catalina.policy to verify that this is a v5.5 config
+			// check for catalina.policy to verify that this is a v8.0 config
 			InputStream in = new FileInputStream(path.append("catalina.policy").toFile());
 			in.read();
 			in.close();
@@ -279,7 +279,7 @@
 				return;
 			monitor.done();
 		} catch (Exception e) {
-			Trace.trace(Trace.WARNING, "Could not load Tomcat v5.5 configuration from " + path.toOSString() + ": " + e.getMessage());
+			Trace.trace(Trace.WARNING, "Could not load Tomcat v8.0 configuration from " + path.toOSString() + ": " + e.getMessage());
 			throw new CoreException(new Status(IStatus.ERROR, TomcatPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorCouldNotLoadConfiguration, path.toOSString()), e));
 		}
 	}
@@ -363,7 +363,7 @@
 				throw new Exception("Cancelled");
 			monitor.done();
 		} catch (Exception e) {
-			Trace.trace(Trace.WARNING, "Could not reload Tomcat v5.5 configuration from: " + folder.getFullPath() + ": " + e.getMessage());
+			Trace.trace(Trace.WARNING, "Could not reload Tomcat v8.0 configuration from: " + folder.getFullPath() + ": " + e.getMessage());
 			throw new CoreException(new Status(IStatus.ERROR, TomcatPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorCouldNotLoadConfiguration, folder.getFullPath().toOSString()), e));
 		}
 	}
@@ -422,7 +422,7 @@
 				return;
 			monitor.done();
 		} catch (Exception e) {
-			Trace.trace(Trace.SEVERE, "Could not save Tomcat v5.5 configuration to " + path, e);
+			Trace.trace(Trace.SEVERE, "Could not save Tomcat v8.0 configuration to " + path, e);
 			throw new CoreException(new Status(IStatus.ERROR, TomcatPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorCouldNotSaveConfiguration, new String[] {e.getLocalizedMessage()}), e));
 		}
 	}
@@ -514,7 +514,7 @@
 				return;
 			monitor.done();
 		} catch (Exception e) {
-			Trace.trace(Trace.SEVERE, "Could not save Tomcat v5.5 configuration to " + folder.toString(), e);
+			Trace.trace(Trace.SEVERE, "Could not save Tomcat v8.0 configuration to " + folder.toString(), e);
 			throw new CoreException(new Status(IStatus.ERROR, TomcatPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorCouldNotSaveConfiguration, new String[] {e.getLocalizedMessage()}), e));
 		}
 	}
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat85Configuration.java b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat85Configuration.java
new file mode 100644
index 0000000..b229015
--- /dev/null
+++ b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat85Configuration.java
@@ -0,0 +1,710 @@
+/**********************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *    IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.jst.server.tomcat.core.internal;
+
+import java.io.BufferedWriter;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileWriter;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jst.server.tomcat.core.internal.xml.Factory;
+import org.eclipse.jst.server.tomcat.core.internal.xml.XMLUtil;
+import org.eclipse.jst.server.tomcat.core.internal.xml.server40.Connector;
+import org.eclipse.jst.server.tomcat.core.internal.xml.server40.Context;
+import org.eclipse.jst.server.tomcat.core.internal.xml.server40.Listener;
+import org.eclipse.jst.server.tomcat.core.internal.xml.server40.Server;
+import org.eclipse.jst.server.tomcat.core.internal.xml.server40.ServerInstance;
+import org.eclipse.jst.server.tomcat.core.internal.xml.server40.Service;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.wst.server.core.ServerPort;
+import org.w3c.dom.Document;
+import org.xml.sax.InputSource;
+/**
+ * Tomcat v8.5 server configuration.
+ */
+public class Tomcat85Configuration extends TomcatConfiguration {
+	protected static final String DEFAULT_SERVICE = "Catalina";
+	protected static final String EOL = System.getProperty("line.separator");
+	protected Server server;
+	protected ServerInstance serverInstance;
+	protected Factory serverFactory;
+	protected boolean isServerDirty;
+
+	protected WebAppDocument webAppDocument;
+
+	protected Document contextDocument;
+
+	protected Document tomcatUsersDocument;
+
+	protected String policyFile;
+
+	protected String propertiesFile;
+	
+	protected static final Map<String, String> protocolHandlerMap = new HashMap<String, String>();
+	static {
+		protocolHandlerMap.put("org.apache.coyote.http11.Http11Protocol", "HTTP/1.1");
+		protocolHandlerMap.put("org.apache.coyote.http11.Http11NioProtocol", "HTTP/1.1");
+		protocolHandlerMap.put("org.apache.coyote.http11.Http11AprProtocol", "HTTP/1.1");
+		protocolHandlerMap.put("org.apache.coyote.ajp.AjpAprProtocol", "AJP/1.3");
+		protocolHandlerMap.put("org.apache.jk.server.JkCoyoteHandler", "AJP/1.3");
+	}
+	
+	/**
+	 * Tomcat85Configuration constructor.
+	 * 
+	 * @param path a path
+	 */
+	public Tomcat85Configuration(IFolder path) {
+		super(path);
+	}
+
+	/**
+	 * Return the port number.
+	 * @return int
+	 */
+	public ServerPort getMainPort() {
+		Iterator iterator = getServerPorts().iterator();
+		while (iterator.hasNext()) {
+			ServerPort port = (ServerPort) iterator.next();
+			// Return only an HTTP port from the selected Service
+			if (port.getProtocol().toLowerCase().equals("http") && port.getId().indexOf('/') < 0)
+				return port;
+		}
+		return null;
+	}
+	
+	/**
+	 * Returns the mime mappings.
+	 * @return java.util.List
+	 */
+	public List getMimeMappings() {
+		return webAppDocument.getMimeMappings();
+	}
+
+	/**
+	 * Returns a list of ServerPorts that this configuration uses.
+	 *
+	 * @return java.util.List
+	 */
+	public List getServerPorts() {
+		List<ServerPort> ports = new ArrayList<ServerPort>();
+	
+		// first add server port
+		try {
+			int port = Integer.parseInt(server.getPort());
+			ports.add(new ServerPort("server", Messages.portServer, port, "TCPIP"));
+		} catch (Exception e) {
+			// ignore
+		}
+	
+		// add connectors
+		try {
+			String instanceServiceName = serverInstance.getService().getName();
+			int size = server.getServiceCount();
+			for (int i = 0; i < size; i++) {
+				Service service = server.getService(i);
+				int size2 = service.getConnectorCount();
+				for (int j = 0; j < size2; j++) {
+					Connector connector = service.getConnector(j);
+					String name = "HTTP/1.1";
+					String protocol2 = "HTTP";
+					boolean advanced = true;
+					String[] contentTypes = null;
+					int port = -1;
+					try {
+						port = Integer.parseInt(connector.getPort());
+					} catch (Exception e) {
+						// ignore
+					}
+					String protocol = connector.getProtocol();
+					if (protocol != null && protocol.length() > 0) {
+						if (protocol.startsWith("HTTP")) {
+							name = protocol;
+						}
+						else if (protocol.startsWith("AJP")) {
+							name = protocol;
+							protocol2 = "AJP"; 
+						}
+						else {
+							// Get Tomcat equivalent name if protocol handler class specified
+							name = protocolHandlerMap.get(protocol);
+							if (name != null) {
+								// Prepare simple protocol string for ServerPort protocol
+								int index = name.indexOf('/');
+								if (index > 0)
+									protocol2 = name.substring(0, index);
+								else
+									protocol2 = name;
+							}
+							// Specified protocol is unknown, just use as is
+							else {
+								name = protocol;
+								protocol2 = protocol;
+							}
+						}
+					}
+					if (protocol2.toLowerCase().equals("http"))
+						contentTypes = new String[] { "web", "webservices" };
+					String secure = connector.getSecure();
+					if (secure != null && secure.length() > 0) {
+						name = "SSL";
+						protocol2 = "SSL";
+					} else
+						advanced = false;
+					String portId;
+					if (instanceServiceName != null && instanceServiceName.equals(service.getName()))
+						portId = Integer.toString(j);
+					else
+						portId = i +"/" + j;
+					ports.add(new ServerPort(portId, name, port, protocol2, contentTypes, advanced));
+				}
+			}
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error getting server ports", e);
+		}
+		return ports;
+	}
+	
+	/**
+	 * Return a list of the web modules in this server.
+	 * @return java.util.List
+	 */
+	public List getWebModules() {
+		List<WebModule> list = new ArrayList<WebModule>();
+	
+		try {
+			Context [] contexts = serverInstance.getContexts();
+			if (contexts != null) {
+				for (int i = 0; i < contexts.length; i++) {
+					Context context = contexts[i];
+					String reload = context.getReloadable();
+					if (reload == null)
+						reload = "false";
+					WebModule module = new WebModule(context.getPath(), 
+						context.getDocBase(), context.getSource(),
+						reload.equalsIgnoreCase("true") ? true : false);
+					list.add(module);
+				}
+			}
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error getting project refs", e);
+		}
+		return list;
+	}
+	
+	/**
+	 * @see TomcatConfiguration#getServerWorkDirectory(IPath)
+	 */
+	public IPath getServerWorkDirectory(IPath basePath) {
+		return serverInstance.getHostWorkDirectory(basePath);
+	}
+
+	/**
+	 * @see TomcatConfiguration#getContextWorkDirectory(IPath, ITomcatWebModule)
+	 */
+	public IPath getContextWorkDirectory(IPath basePath, ITomcatWebModule module) {
+		Context context = serverInstance.getContext(module.getPath());
+		if (context != null)
+			return serverInstance.getContextWorkDirectory(basePath, context);
+		
+		return null;
+	}
+
+	/**
+	 * @see TomcatConfiguration#load(IPath, IProgressMonitor)
+	 */
+	public void load(IPath path, IProgressMonitor monitor) throws CoreException {
+		try {
+			monitor = ProgressUtil.getMonitorFor(monitor);
+			monitor.beginTask(Messages.loadingTask, 7);
+			
+			// check for catalina.policy to verify that this is a v5.5 config
+			InputStream in = new FileInputStream(path.append("catalina.policy").toFile());
+			in.read();
+			in.close();
+			monitor.worked(1);
+
+			serverFactory = new Factory();
+			serverFactory.setPackageName("org.eclipse.jst.server.tomcat.core.internal.xml.server40");
+			server = (Server) serverFactory.loadDocument(new FileInputStream(path.append("server.xml").toFile()));
+			serverInstance = new ServerInstance(server, null, null);
+			monitor.worked(1);
+
+			webAppDocument = new WebAppDocument(path.append("web.xml"));
+			monitor.worked(1);
+			
+			File file = path.append("context.xml").toFile();
+			if (file.exists())
+				contextDocument = XMLUtil.getDocumentBuilder().parse(new InputSource(new FileInputStream(file)));
+			monitor.worked(1);
+			
+			tomcatUsersDocument = XMLUtil.getDocumentBuilder().parse(new InputSource(new FileInputStream(path.append("tomcat-users.xml").toFile())));
+			monitor.worked(1);
+			
+			// load policy file
+			policyFile = TomcatVersionHelper.getFileContents(new FileInputStream(path.append("catalina.policy").toFile()));
+			monitor.worked(1);
+
+			// load properties file
+			file = path.append("catalina.properties").toFile();
+			if (file.exists())
+				propertiesFile = TomcatVersionHelper.getFileContents(new FileInputStream(file));
+			else
+				propertiesFile = null;
+			monitor.worked(1);
+			
+			if (monitor.isCanceled())
+				return;
+			monitor.done();
+		} catch (Exception e) {
+			Trace.trace(Trace.WARNING, "Could not load Tomcat v8.5 configuration from " + path.toOSString() + ": " + e.getMessage());
+			throw new CoreException(new Status(IStatus.ERROR, TomcatPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorCouldNotLoadConfiguration, path.toOSString()), e));
+		}
+	}
+
+	/**
+	 * @see TomcatConfiguration#importFromPath(IPath, boolean, IProgressMonitor)
+	 */
+	public void importFromPath(IPath path, boolean isTestEnv, IProgressMonitor monitor) throws CoreException {
+		load(path, monitor);
+		
+		// for test environment, remove existing contexts since a separate
+		// catalina.base will be used
+		if (isTestEnv) {
+			while (serverInstance.removeContext(0)) {
+				// no-op
+			}
+		}
+	}
+
+	/**
+	 * @see TomcatConfiguration#load(IFolder, IProgressMonitor)
+	 */
+	public void load(IFolder folder, IProgressMonitor monitor) throws CoreException {
+		try {
+			monitor = ProgressUtil.getMonitorFor(monitor);
+			monitor.beginTask(Messages.loadingTask, 1200);
+	
+			// check for catalina.policy to verify that this is a v4.0 config
+			IFile file = folder.getFile("catalina.policy");
+			if (!file.exists())
+				throw new CoreException(new Status(IStatus.WARNING, TomcatPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorCouldNotLoadConfiguration, folder.getFullPath().toOSString()), null));
+	
+			// load server.xml
+			file = folder.getFile("server.xml");
+			InputStream in = file.getContents();
+			serverFactory = new Factory();
+			serverFactory.setPackageName("org.eclipse.jst.server.tomcat.core.internal.xml.server40");
+			server = (Server) serverFactory.loadDocument(in);
+			serverInstance = new ServerInstance(server, null, null);
+			monitor.worked(200);
+	
+			// load web.xml
+			file = folder.getFile("web.xml");
+			webAppDocument = new WebAppDocument(file);
+			monitor.worked(200);
+	
+			// load context.xml
+			file = folder.getFile("context.xml");
+			if (file.exists()) {
+				in = file.getContents();
+				contextDocument = XMLUtil.getDocumentBuilder().parse(new InputSource(in));
+			}
+			else
+				contextDocument = null;
+			monitor.worked(200);
+		
+			// load tomcat-users.xml
+			file = folder.getFile("tomcat-users.xml");
+			in = file.getContents();
+			
+			tomcatUsersDocument = XMLUtil.getDocumentBuilder().parse(new InputSource(in));
+			monitor.worked(200);
+		
+			// load catalina.policy
+			file = folder.getFile("catalina.policy");
+			in = file.getContents();
+			policyFile = TomcatVersionHelper.getFileContents(in);
+			monitor.worked(200);
+	
+			// load catalina.properties
+			file = folder.getFile("catalina.properties");
+			if (file.exists()) {
+				in = file.getContents();
+				propertiesFile = TomcatVersionHelper.getFileContents(in);
+			}
+			else
+				propertiesFile = null;
+			monitor.worked(200);
+			
+			if (monitor.isCanceled())
+				throw new Exception("Cancelled");
+			monitor.done();
+		} catch (Exception e) {
+			Trace.trace(Trace.WARNING, "Could not reload Tomcat v8.5 configuration from: " + folder.getFullPath() + ": " + e.getMessage());
+			throw new CoreException(new Status(IStatus.ERROR, TomcatPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorCouldNotLoadConfiguration, folder.getFullPath().toOSString()), e));
+		}
+	}
+
+	/**
+	 * Save to the given directory.
+	 * @param path a path
+	 * @param forceDirty boolean
+	 * @param monitor a progress monitor
+	 * @exception CoreException
+	 */
+	protected void save(IPath path, boolean forceDirty, IProgressMonitor monitor) throws CoreException {
+		try {
+			monitor = ProgressUtil.getMonitorFor(monitor);
+			monitor.beginTask(Messages.savingTask, 5);
+			
+			// make sure directory exists
+			if (!path.toFile().exists()) {
+				forceDirty = true;
+				path.toFile().mkdir();
+			}
+			monitor.worked(1);
+			
+			// save files
+			if (forceDirty || isServerDirty) {
+				serverFactory.save(path.append("server.xml").toOSString());
+				isServerDirty = false;
+			}
+			monitor.worked(1);
+			
+			webAppDocument.save(path.append("web.xml").toOSString(), forceDirty);
+			monitor.worked(1);
+			
+			if (forceDirty && contextDocument != null)
+				XMLUtil.save(path.append("context.xml").toOSString(), contextDocument);
+			monitor.worked(1);
+			
+			if (forceDirty)
+				XMLUtil.save(path.append("tomcat-users.xml").toOSString(), tomcatUsersDocument);
+			monitor.worked(1);
+			
+			if (forceDirty) {
+				BufferedWriter bw = new BufferedWriter(new FileWriter(path.append("catalina.policy").toFile()));
+				bw.write(policyFile);
+				bw.close();
+			}
+			monitor.worked(1);
+			if (propertiesFile != null && forceDirty) {
+				BufferedWriter bw = new BufferedWriter(new FileWriter(path.append("catalina.properties").toFile()));
+				bw.write(propertiesFile);
+				bw.close();
+			}
+			monitor.worked(1);
+			
+			if (monitor.isCanceled())
+				return;
+			monitor.done();
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Could not save Tomcat v8.5 configuration to " + path, e);
+			throw new CoreException(new Status(IStatus.ERROR, TomcatPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorCouldNotSaveConfiguration, new String[] {e.getLocalizedMessage()}), e));
+		}
+	}
+
+	/**
+	 * Save to the given directory.  All configuration files
+	 * are forced to be saved.
+	 * 
+	 * @param path Desination path for the configuration files.
+	 * @param monitor A progress monitor
+	 * @exception CoreException
+	 */
+	public void save(IPath path, IProgressMonitor monitor) throws CoreException {
+		save(path, true, monitor);
+	}
+
+	/**
+	 * Save the information held by this object to the given directory.
+	 *
+	 * @param folder a folder
+	 * @param monitor a progress monitor
+	 * @throws CoreException
+	 */
+	public void save(IFolder folder, IProgressMonitor monitor) throws CoreException {
+		try {
+			monitor = ProgressUtil.getMonitorFor(monitor);
+			monitor.beginTask(Messages.savingTask, 1200);
+	
+			// save server.xml
+			byte[] data = serverFactory.getContents();
+			InputStream in = new ByteArrayInputStream(data);
+			IFile file = folder.getFile("server.xml");
+			if (file.exists()) {
+				if (isServerDirty)
+					file.setContents(in, true, true, ProgressUtil.getSubMonitorFor(monitor, 200));
+				else
+					monitor.worked(200);
+			} else
+				file.create(in, true, ProgressUtil.getSubMonitorFor(monitor, 200));
+			isServerDirty = false;
+			
+			// save web.xml
+			webAppDocument.save(folder.getFile("web.xml"), ProgressUtil.getSubMonitorFor(monitor, 200));
+			
+			// save context.xml
+			if (contextDocument != null) {
+				data = XMLUtil.getContents(contextDocument);
+				in = new ByteArrayInputStream(data);
+				file = folder.getFile("context.xml");
+				if (file.exists())
+					monitor.worked(200);
+					//file.setContents(in, true, true, ProgressUtil.getSubMonitorFor(monitor, 200));
+				else
+					file.create(in, true, ProgressUtil.getSubMonitorFor(monitor, 200));
+			}
+			
+			// save tomcat-users.xml
+			data = XMLUtil.getContents(tomcatUsersDocument);
+			in = new ByteArrayInputStream(data);
+			file = folder.getFile("tomcat-users.xml");
+			if (file.exists())
+				monitor.worked(200);
+				//file.setContents(in, true, true, ProgressUtil.getSubMonitorFor(monitor, 200));
+			else
+				file.create(in, true, ProgressUtil.getSubMonitorFor(monitor, 200));
+			
+			// save catalina.policy
+			in = new ByteArrayInputStream(policyFile.getBytes());
+			file = folder.getFile("catalina.policy");
+			if (file.exists())
+				monitor.worked(200);
+				//file.setContents(in, true, true, ProgressUtil.getSubMonitorFor(monitor, 200));
+			else
+				file.create(in, true, ProgressUtil.getSubMonitorFor(monitor, 200));
+			
+			// save catalina.properties
+			if (propertiesFile != null) {
+				in = new ByteArrayInputStream(propertiesFile.getBytes());
+				file = folder.getFile("catalina.properties");
+				if (file.exists())
+					monitor.worked(200);
+					//file.setContents(in, true, true, ProgressUtil.getSubMonitorFor(monitor, 200));
+				else
+					file.create(in, true, ProgressUtil.getSubMonitorFor(monitor, 200));
+			} else
+				monitor.worked(200);
+			
+			if (monitor.isCanceled())
+				return;
+			monitor.done();
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Could not save Tomcat v8.5 configuration to " + folder.toString(), e);
+			throw new CoreException(new Status(IStatus.ERROR, TomcatPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorCouldNotSaveConfiguration, new String[] {e.getLocalizedMessage()}), e));
+		}
+	}
+
+	protected static boolean hasMDBListener(Server server) {
+		if (server == null)
+			return false;
+		
+		int count = server.getListenerCount();
+		if (count == 0)
+			return false;
+			
+		for (int i = 0; i < count; i++) {
+			Listener listener = server.getListener(i);
+			if (listener != null && listener.getClassName() != null && listener.getClassName().indexOf("mbean") >= 0)
+				return true;
+		}
+		return false;
+	}
+	
+	/**
+	 * @see ITomcatConfigurationWorkingCopy#addMimeMapping(int, IMimeMapping)
+	 */
+	public void addMimeMapping(int index, IMimeMapping map) {
+		webAppDocument.addMimeMapping(index, map);
+		firePropertyChangeEvent(ADD_MAPPING_PROPERTY, new Integer(index), map);
+	}
+
+	/**
+	 * @see ITomcatConfigurationWorkingCopy#addWebModule(int, ITomcatWebModule)
+	 */
+	public void addWebModule(int index, ITomcatWebModule module) {
+		try {
+			Context context = serverInstance.createContext(index);
+			if (context != null) {
+				context.setDocBase(module.getDocumentBase());
+				context.setPath(module.getPath());
+				context.setReloadable(module.isReloadable() ? "true" : "false");
+				if (module.getMemento() != null && module.getMemento().length() > 0)
+					context.setSource(module.getMemento());
+				isServerDirty = true;
+				firePropertyChangeEvent(ADD_WEB_MODULE_PROPERTY, null, module);
+			}
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error adding web module " + module.getPath(), e);
+		}
+	}
+
+	/**
+	 * Change the extension of a mime mapping.
+	 * 
+	 * @param index
+	 * @param map
+	 */
+	public void modifyMimeMapping(int index, IMimeMapping map) {
+		webAppDocument.modifyMimeMapping(index, map);
+		firePropertyChangeEvent(MODIFY_MAPPING_PROPERTY, new Integer(index), map);
+	}
+
+	/**
+	 * Modify the port with the given id.
+	 *
+	 * @param id java.lang.String
+	 * @param port int
+	 */
+	public void modifyServerPort(String id, int port) {
+		try {
+			if ("server".equals(id)) {
+				server.setPort(port + "");
+				isServerDirty = true;
+				firePropertyChangeEvent(MODIFY_PORT_PROPERTY, id, new Integer(port));
+				return;
+			}
+	
+			int i = id.indexOf("/");
+			// If a connector in the instance Service
+			if (i < 0) {
+				int connNum = Integer.parseInt(id);
+				Connector connector = serverInstance.getConnector(connNum);
+				if (connector != null) {
+					connector.setPort(port + "");
+					isServerDirty = true;
+					firePropertyChangeEvent(MODIFY_PORT_PROPERTY, id, new Integer(port));
+				}
+			}
+			// Else a connector in another Service
+			else {
+				int servNum = Integer.parseInt(id.substring(0, i));
+				int connNum = Integer.parseInt(id.substring(i + 1));
+				
+				Service service = server.getService(servNum);
+				Connector connector = service.getConnector(connNum);
+				connector.setPort(port + "");
+				isServerDirty = true;
+				firePropertyChangeEvent(MODIFY_PORT_PROPERTY, id, new Integer(port));
+			}
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error modifying server port " + id, e);
+		}
+	}
+	/**
+	 * Change a web module.
+	 * @param index int
+	 * @param docBase java.lang.String
+	 * @param path java.lang.String
+	 * @param reloadable boolean
+	 */
+	public void modifyWebModule(int index, String docBase, String path, boolean reloadable) {
+		try {
+			Context context = serverInstance.getContext(index);
+			if (context != null) {
+				context.setPath(path);
+				context.setDocBase(docBase);
+				context.setReloadable(reloadable ? "true" : "false");
+				isServerDirty = true;
+				WebModule module = new WebModule(path, docBase, null, reloadable);
+				firePropertyChangeEvent(MODIFY_WEB_MODULE_PROPERTY, new Integer(index), module);
+			}
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error modifying web module " + index, e);
+		}
+	}
+
+	/**
+	 * Removes a mime mapping.
+	 * @param index int
+	 */
+	public void removeMimeMapping(int index) {
+		webAppDocument.removeMimeMapping(index);
+		firePropertyChangeEvent(REMOVE_MAPPING_PROPERTY, null, new Integer(index));
+	}
+
+	/**
+	 * Removes a web module.
+	 * @param index int
+	 */
+	public void removeWebModule(int index) {
+		try {
+			serverInstance.removeContext(index);
+			isServerDirty = true;
+			firePropertyChangeEvent(REMOVE_WEB_MODULE_PROPERTY, null, new Integer(index));
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error removing module ref " + index, e);
+		}
+	}
+
+	/**
+	 * Add context configuration found in META-INF/context.xml files
+	 * present in projects to published server.xml.
+	 * 
+	 * @param baseDir path to catalina instance directory
+	 * @param deployDir path to deployment directory
+	 * @param monitor a progress monitor or null
+	 * @return result of operation
+	 */
+	protected IStatus publishContextConfig(IPath baseDir, IPath deployDir, IProgressMonitor monitor) {
+		return TomcatVersionHelper.publishCatalinaContextConfig(baseDir, deployDir, monitor);
+	}
+	
+	/**
+	 * Update contexts in server.xml to serve projects directly without
+	 * publishing.
+	 * 
+	 * @param baseDir path to catalina instance directory
+	 * @param monitor a progress monitor or null
+	 * @return result of operation
+	 */
+	protected IStatus updateContextsToServeDirectly(IPath baseDir, String tomcatVersion, String loader, IProgressMonitor monitor) {
+		return TomcatVersionHelper.updateContextsToServeDirectly(baseDir, tomcatVersion, loader, true, monitor);
+	}
+
+	/**
+	 * Cleanup the server instance.  This consists of deleting the work
+	 * directory associated with Contexts that are going away in the
+	 * up coming publish.
+	 * 
+	 * @param baseDir path to server instance directory, i.e. catalina.base
+	 * @param installDir path to server installation directory (not currently used)
+	 * @param monitor a progress monitor or null
+	 * @return MultiStatus containing results of the cleanup operation
+	 */
+	protected IStatus cleanupServer(IPath baseDir, IPath installDir, boolean removeKeptContextFiles, IProgressMonitor monitor) {
+		List modules = getWebModules();
+		return TomcatVersionHelper.cleanupCatalinaServer(baseDir, installDir, removeKeptContextFiles, modules, monitor);
+	}
+
+	/**
+	 * @see TomcatConfiguration#localizeConfiguration(IPath, IPath, TomcatServer, IProgressMonitor)
+	 */
+	public IStatus localizeConfiguration(IPath baseDir, IPath deployDir, TomcatServer tomcatServer, IProgressMonitor monitor) {
+		return TomcatVersionHelper.localizeConfiguration(baseDir, deployDir, tomcatServer, monitor);
+	}
+}
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat85Handler.java b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat85Handler.java
new file mode 100644
index 0000000..f43b6c7
--- /dev/null
+++ b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat85Handler.java
@@ -0,0 +1,188 @@
+/**********************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *    IBM Corporation - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.jst.server.tomcat.core.internal;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jdt.launching.IRuntimeClasspathEntry;
+import org.eclipse.jdt.launching.JavaRuntime;
+import org.eclipse.wst.server.core.IModule;
+/**
+ * Tomcat 85 handler.
+ */
+public class Tomcat85Handler implements ITomcatVersionHandler {
+	/**
+	 * @see ITomcatVersionHandler#verifyInstallPath(IPath)
+	 */
+	public IStatus verifyInstallPath(IPath installPath) {
+		IStatus result = TomcatVersionHelper.checkCatalinaVersion(installPath, TomcatPlugin.TOMCAT_85);
+		// If check was canceled, use folder check
+		if (result.getSeverity() == IStatus.CANCEL) {
+			result = TomcatPlugin.verifyInstallPathWithFolderCheck(installPath, TomcatPlugin.TOMCAT_85);
+		}
+		return result;
+	}
+	
+	/**
+	 * @see ITomcatVersionHandler#getRuntimeClass()
+	 */
+	public String getRuntimeClass() {
+		return "org.apache.catalina.startup.Bootstrap";
+	}
+	
+	/**
+	 * @see ITomcatVersionHandler#getRuntimeClasspath(IPath, IPath)
+	 */
+	public List getRuntimeClasspath(IPath installPath, IPath configPath) {
+		List<IRuntimeClasspathEntry> cp = new ArrayList<IRuntimeClasspathEntry>();
+		
+		// 8.5 - add bootstrap.jar and tomcat-juli.jar from the Tomcat bin directory
+		IPath binPath = installPath.append("bin");
+		if (binPath.toFile().exists()) {
+			IPath path = binPath.append("bootstrap.jar");
+			cp.add(JavaRuntime.newArchiveRuntimeClasspathEntry(path));
+			// Add tomcat-juli.jar if it exists
+			path = binPath.append("tomcat-juli.jar");
+			if (path.toFile().exists()) {
+				cp.add(JavaRuntime.newArchiveRuntimeClasspathEntry(path));
+			}
+			// If tomcat-juli.jar is not found in the install, check the config directory
+			else if (configPath != null){
+				path = configPath.append("bin/tomcat-juli.jar");
+				if (path.toFile().exists()) {
+					cp.add(JavaRuntime.newArchiveRuntimeClasspathEntry(path));
+				}
+			}
+		}
+		
+		return cp;
+	}
+
+	/**
+	 * @see ITomcatVersionHandler#getRuntimeProgramArguments(IPath, boolean, boolean)
+	 */
+	public String[] getRuntimeProgramArguments(IPath configPath, boolean debug, boolean starting) {
+		List<String> list = new ArrayList<String>();
+
+		if (starting)
+			list.add("start");
+		else
+			list.add("stop");
+		
+		String[] temp = new String[list.size()];
+		list.toArray(temp);
+		return temp;
+	}
+
+	/**
+	 * @see ITomcatVersionHandler#getExcludedRuntimeProgramArguments(boolean, boolean)
+	 */
+	public String[] getExcludedRuntimeProgramArguments(boolean debug, boolean starting) {
+		return null;
+	}
+	
+	/**
+	 * @see ITomcatVersionHandler#getRuntimeVMArguments(IPath, IPath, IPath, boolean)
+	 */
+	public String[] getRuntimeVMArguments(IPath installPath, IPath configPath, IPath deployPath, boolean isTestEnv) {
+		return TomcatVersionHelper.getCatalinaVMArguments(installPath, configPath, deployPath, getEndorsedDirectories(installPath), isTestEnv);
+	}
+
+	/**
+	 * @see ITomcatVersionHandler#getRuntimePolicyFile(IPath)
+	 */
+	public String getRuntimePolicyFile(IPath configPath) {
+		return configPath.append("conf").append("catalina.policy").toOSString();
+	}
+
+	/**
+	 * @see ITomcatVersionHandler#canAddModule(IModule)
+	 */
+	public IStatus canAddModule(IModule module) {
+		String version = module.getModuleType().getVersion();
+		if ("2.2".equals(version) || "2.3".equals(version) || "2.4".equals(version) || "2.5".equals(version)
+				|| "3.0".equals(version) || "3.1".equals(version))
+			return Status.OK_STATUS;
+		
+		return new Status(IStatus.ERROR, TomcatPlugin.PLUGIN_ID, 0, Messages.errorSpec85, null);
+	}
+
+	/**
+	 * @see ITomcatVersionHandler#getRuntimeBaseDirectory(TomcatServer)
+	 */
+	public IPath getRuntimeBaseDirectory(TomcatServer server) {
+		return TomcatVersionHelper.getStandardBaseDirectory(server);
+	}
+
+	/**
+	 * @see ITomcatVersionHandler#prepareRuntimeDirectory(IPath)
+	 */
+	public IStatus prepareRuntimeDirectory(IPath baseDir) {
+		return TomcatVersionHelper.createCatalinaInstanceDirectory(baseDir);
+	}
+
+	/**
+	 * @see ITomcatVersionHandler#prepareDeployDirectory(IPath)
+	 */
+	public IStatus prepareDeployDirectory(IPath deployPath) {
+		return TomcatVersionHelper.createDeploymentDirectory(deployPath,
+				TomcatVersionHelper.DEFAULT_WEBXML_SERVLET25);
+	}
+
+	/**
+	 * @see ITomcatVersionHandler#prepareForServingDirectly(IPath, TomcatServer)
+	 */
+	public IStatus prepareForServingDirectly(IPath baseDir, TomcatServer server, String tomcatVersion) {
+		// Nothing beyond configuration required for Tomcat 8
+		return Status.OK_STATUS;
+	}
+
+	/**
+	 * @see ITomcatVersionHandler#getSharedLoader(IPath)
+	 */
+	public String getSharedLoader(IPath baseDir) {
+		return "common";
+	}
+	
+	/**
+	 * Returns true since Tomcat 8.5 supports this feature.
+	 * 
+	 * @return true since feature is supported
+	 */
+	public boolean supportsServeModulesWithoutPublish() {
+		return true;
+	}
+
+	/**
+	 * @see ITomcatVersionHandler#supportsDebugArgument()
+	 */
+	public boolean supportsDebugArgument() {
+		return false;
+	}
+
+	/**
+	 * @see ITomcatVersionHandler#supportsSeparateContextFiles()
+	 */
+	public boolean supportsSeparateContextFiles() {
+		return true;
+	}
+
+	/**
+	 * @see ITomcatVersionHandler#getEndorsedDirectories(IPath)
+	 */
+	public String getEndorsedDirectories(IPath installPath) {
+		return installPath.append("endorsed").toOSString();
+	}	
+}
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat85PublishModuleVisitor.java b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat85PublishModuleVisitor.java
new file mode 100644
index 0000000..648c1b5
--- /dev/null
+++ b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat85PublishModuleVisitor.java
@@ -0,0 +1,270 @@
+/**********************************************************************
+ * Copyright (c) 2016 SAS Institute and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *    SAS Institute - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.jst.server.tomcat.core.internal;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jst.server.tomcat.core.internal.xml.server40.Context;
+import org.eclipse.jst.server.tomcat.core.internal.xml.server40.JarResources;
+import org.eclipse.jst.server.tomcat.core.internal.xml.server40.PostResources;
+import org.eclipse.jst.server.tomcat.core.internal.xml.server40.PreResources;
+import org.eclipse.jst.server.tomcat.core.internal.xml.server40.ServerInstance;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
+import org.eclipse.wst.common.componentcore.resources.IVirtualResource;
+import org.eclipse.wst.server.core.IModule;
+import org.eclipse.wst.server.core.ServerUtil;
+
+public class Tomcat85PublishModuleVisitor extends TomcatPublishModuleVisitor {
+
+	/**
+	 * Instantiate a new Tomcat85PublishModuleVisitor
+	 * 
+	 * @param baseDir catalina base path
+	 * @param tomcatVersion tomcat version
+	 * @param serverInstance ServerInstance containing server.xml contents
+	 * @param sharedLoader string value for shared.loader catalina configuration property
+	 * @param enableMetaInfResources flag to indicate if Servlet 3.0 "META-INF/resources" feature should be supported
+	 */
+	Tomcat85PublishModuleVisitor(IPath baseDir, String tomcatVersion, ServerInstance serverInstance, String sharedLoader, boolean enableMetaInfResources) {
+		super(baseDir, tomcatVersion, serverInstance, sharedLoader, enableMetaInfResources);
+	}
+
+    /**
+     * {@inheritDoc}
+     */
+	@Override
+    public void endVisitWebComponent(IVirtualComponent component)
+            throws CoreException {
+
+        // track context changes, don't rewrite if not needed
+        boolean dirty = false;
+
+        IModule module = ServerUtil.getModule(component.getProject());
+
+        // we need this for the user-specified context path
+        Context context = findContext(module);
+        if (context == null) {
+        	String name = module != null ? module.getName() : component.getName();
+    		Trace.trace(Trace.SEVERE, "Could not find context for module " + name);
+    		throw new CoreException(new Status(IStatus.ERROR, TomcatPlugin.PLUGIN_ID, 0,
+    				NLS.bind(Messages.errorPublishContextNotFound, name), null));
+        }
+
+		dirty = includeProjectContextXml(component, context);
+		dirty = updateDocBaseAndPath(component, context);
+
+		// Add WEB-INF/classes elements as PreResources
+		for (Iterator iterator = virtualClassClasspathElements.iterator();
+				iterator.hasNext();) {
+			Object virtualClassClasspathElement = iterator.next();
+			PreResources preResources = (PreResources)context.getResources().createElement("PreResources");
+			preResources.setClassName("org.apache.catalina.webresources.DirResourceSet");
+			preResources.setBase(virtualClassClasspathElement.toString());
+			preResources.setWebAppMount("/WEB-INF/classes");
+			preResources.setInternalPath("/");
+			preResources.setClassLoaderOnly("false");
+		}
+		virtualClassClasspathElements.clear();
+
+		// Add Jars as JarResources if a jar, or as PostResources if a utility project
+		for (Iterator iterator = virtualJarClasspathElements.iterator();
+				iterator.hasNext();) {
+			Object virtualJarClassClasspathElement = iterator.next();
+			String jarPath = virtualJarClassClasspathElement.toString();
+			if (jarPath.endsWith(".jar")) {
+				JarResources jarResources = (JarResources)context.getResources().createElement("JarResources");
+				jarResources.setClassName("org.apache.catalina.webresources.JarResourceSet");
+				jarResources.setBase(jarPath);
+				jarResources.setWebAppMount("/WEB-INF/classes");
+				jarResources.setInternalPath("/");
+				jarResources.setClassLoaderOnly("true");
+			}
+			else {
+				PostResources postResources = (PostResources)context.getResources().createElement("PostResources");
+				postResources.setClassName("org.apache.catalina.webresources.DirResourceSet");
+				postResources.setBase(jarPath);
+				postResources.setWebAppMount("/WEB-INF/classes");
+				postResources.setInternalPath("/");
+				postResources.setClassLoaderOnly("false");
+				// Map META-INF tld files to WEB-INF
+				File metaInfDir = new File(jarPath + "/META-INF");
+				if (metaInfDir.isDirectory() && metaInfDir.exists()) {
+					// Map META-INF directory directly to /META-INF
+					postResources = (PostResources)context.getResources().createElement("PostResources");
+					postResources.setClassName("org.apache.catalina.webresources.DirResourceSet");
+					postResources.setBase(metaInfDir.getPath());
+					postResources.setWebAppMount("/META-INF");
+					postResources.setInternalPath("/");
+					postResources.setClassLoaderOnly("false");
+
+					File [] tldFiles = metaInfDir.listFiles(new FileFilter() {
+							public boolean accept(File file) {
+								if (file.isFile() && file.getName().endsWith(".tld")) {
+									return true;
+								}
+								return false;
+							}
+						});
+					for (int i = 0; i < tldFiles.length; i++) {
+						postResources = (PostResources)context.getResources().createElement("PostResources");
+						postResources.setClassName("org.apache.catalina.webresources.FileResourceSet");
+						postResources.setBase(tldFiles[0].getPath());
+						postResources.setWebAppMount("/WEB-INF/" + tldFiles[0].getName());
+						postResources.setInternalPath("/");
+						postResources.setClassLoaderOnly("false");
+					}
+				}
+			}
+		}
+		virtualJarClasspathElements.clear();
+
+		Set<String> rtPathsProcessed = new HashSet<String>();
+		Set<String> locationsIncluded = new HashSet<String>();
+		String docBase = context.getDocBase();
+		locationsIncluded.add(docBase);
+		Map<String, String> retryLocations = new HashMap<String, String>();
+		IVirtualResource [] virtualResources = component.getRootFolder().getResources("");
+		// Loop over the module's resources
+		for (int i = 0; i < virtualResources.length; i++) {
+			String rtPath = virtualResources[i].getRuntimePath().toString();
+			// Note: The virtual resources returned only know their runtime path.
+			// Asking for the project path for this resource performs a lookup
+			// that will only return the path for the first mapping for the
+			// runtime path.  Thus use of getUnderlyingResources() is necessary.
+			// However, this returns matching resources from all mappings so
+			// we have to try to keep only those that are mapped directly
+			// to the runtime path in the .components file.
+
+			// If this runtime path has not yet been processed
+			if (!rtPathsProcessed.contains(rtPath)) {
+				// If not a Java related resource
+				if (!"/WEB-INF/classes".equals(rtPath)) {
+					// Get all resources for this runtime path
+					IResource[] underlyingResources = virtualResources[i].getUnderlyingResources();
+					// If resource is mapped to "/", then we know it corresponds directly
+					// to a mapping in the .components file
+					if ("/".equals(rtPath)) {
+						for (int j = 0; j < underlyingResources.length; j++) {
+							IPath resLoc = underlyingResources[j].getLocation();
+							String location = resLoc.toOSString();
+							if (!location.equals(docBase)) {
+								PreResources preResources = (PreResources)context.getResources().createElement("PreResources");
+								preResources.setClassName("org.apache.catalina.webresources.DirResourceSet");
+								preResources.setBase(location);
+								preResources.setWebAppMount("/");
+								preResources.setInternalPath("/");
+								preResources.setClassLoaderOnly("false");
+								// Add to the set of locations included
+								locationsIncluded.add(location);
+							}
+						}
+					}
+					// Else this runtime path is something other than "/"
+					else {
+						int idx = rtPath.lastIndexOf('/');
+						// If a "normal" runtime path
+						if (idx >= 0) {
+							// Get the name of the last segment in the runtime path
+							String lastSegment = rtPath.substring(idx + 1);
+							// Check the underlying resources to determine which correspond to mappings
+							for (int j = 0; j < underlyingResources.length; j++) {
+								IPath resLoc = underlyingResources[j].getLocation();
+								String location = resLoc.toOSString();
+								// If the last segment of the runtime path doesn't match the
+								// the last segment of the location, then we have a direct mapping
+								// from the .contents file.
+								if (!lastSegment.equals(resLoc.lastSegment())) {
+									PreResources preResources = (PreResources)context.getResources().createElement("PreResources");
+									preResources.setClassName("org.apache.catalina.webresources.DirResourceSet");
+									preResources.setBase(location);
+									preResources.setWebAppMount(rtPath);
+									preResources.setInternalPath("/");
+									preResources.setClassLoaderOnly("false");
+									// Add to the set of locations included
+									locationsIncluded.add(location);
+								}
+								// Else last segment of runtime path did match the last segment
+								// of the location.  We likely have a subfolder of a mapping
+								// that matches a portion of the runtime path.
+								else {
+									// Since we can't be sure, save so it can be check again later
+									retryLocations.put(location, rtPath);
+								}
+							}
+						}
+					}
+				}
+				// Add the runtime path to those already processed
+				rtPathsProcessed.add(rtPath);
+			}
+		}
+		// If there are locations to retry, add any not yet included in extra paths setting
+		if (!retryLocations.isEmpty()) {
+			// Remove retry locations already included in the extra paths
+			for (Iterator iterator = retryLocations.keySet().iterator(); iterator.hasNext();) {
+				String location = (String)iterator.next();
+				for (Iterator iterator2 = locationsIncluded.iterator(); iterator2.hasNext();) {
+					String includedLocation = (String)iterator2.next();
+					if (location.equals(includedLocation) || location.startsWith(includedLocation + File.separator)) {
+						iterator.remove();
+						break;
+					}
+				}
+			}
+			// If any entries are left, include them in the extra paths
+			if (!retryLocations.isEmpty()) {
+				for (Iterator iterator = retryLocations.entrySet().iterator(); iterator.hasNext();) {
+					Map.Entry entry = (Map.Entry)iterator.next();
+					String location = (String)entry.getKey();
+					String rtPath = (String)entry.getValue();
+					PreResources preResources = (PreResources)context.getResources().createElement("PreResources");
+					preResources.setClassName("org.apache.catalina.webresources.DirResourceSet");
+					preResources.setBase(location);
+					preResources.setWebAppMount(rtPath);
+					preResources.setInternalPath("/");
+					preResources.setClassLoaderOnly("false");
+				}
+			}
+		}
+		if (!virtualDependentResources.isEmpty()) {
+			for (Map.Entry<String, List<String>> entry : virtualDependentResources.entrySet()) {
+				String rtPath = entry.getKey();
+				List<String> locations = entry.getValue();
+				for (String location : locations) {
+					PostResources postResources = (PostResources)context.getResources().createElement("PostResources");
+					postResources.setClassName("org.apache.catalina.webresources.DirResourceSet");
+					postResources.setBase(location);
+					postResources.setWebAppMount(rtPath.length() > 0 ? rtPath : "/");
+					postResources.setInternalPath("/");
+					postResources.setClassLoaderOnly("false");
+				}
+			}
+		}
+		virtualDependentResources.clear();
+
+		if (dirty) {
+			//TODO If writing to separate context XML files, save "dirty" status for later use
+		}
+	}
+}
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat90Configuration.java b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat90Configuration.java
index d3eecce..455989a 100644
--- a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat90Configuration.java
+++ b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat90Configuration.java
@@ -240,7 +240,7 @@
 			monitor = ProgressUtil.getMonitorFor(monitor);
 			monitor.beginTask(Messages.loadingTask, 7);
 			
-			// check for catalina.policy to verify that this is a v5.5 config
+			// check for catalina.policy to verify that this is a v9.0 config
 			InputStream in = new FileInputStream(path.append("catalina.policy").toFile());
 			in.read();
 			in.close();
@@ -279,7 +279,7 @@
 				return;
 			monitor.done();
 		} catch (Exception e) {
-			Trace.trace(Trace.WARNING, "Could not load Tomcat v5.5 configuration from " + path.toOSString() + ": " + e.getMessage());
+			Trace.trace(Trace.WARNING, "Could not load Tomcat v9.0 configuration from " + path.toOSString() + ": " + e.getMessage());
 			throw new CoreException(new Status(IStatus.ERROR, TomcatPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorCouldNotLoadConfiguration, path.toOSString()), e));
 		}
 	}
@@ -363,7 +363,7 @@
 				throw new Exception("Cancelled");
 			monitor.done();
 		} catch (Exception e) {
-			Trace.trace(Trace.WARNING, "Could not reload Tomcat v5.5 configuration from: " + folder.getFullPath() + ": " + e.getMessage());
+			Trace.trace(Trace.WARNING, "Could not reload Tomcat v9.0 configuration from: " + folder.getFullPath() + ": " + e.getMessage());
 			throw new CoreException(new Status(IStatus.ERROR, TomcatPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorCouldNotLoadConfiguration, folder.getFullPath().toOSString()), e));
 		}
 	}
@@ -422,7 +422,7 @@
 				return;
 			monitor.done();
 		} catch (Exception e) {
-			Trace.trace(Trace.SEVERE, "Could not save Tomcat v5.5 configuration to " + path, e);
+			Trace.trace(Trace.SEVERE, "Could not save Tomcat v9.0 configuration to " + path, e);
 			throw new CoreException(new Status(IStatus.ERROR, TomcatPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorCouldNotSaveConfiguration, new String[] {e.getLocalizedMessage()}), e));
 		}
 	}
@@ -514,7 +514,7 @@
 				return;
 			monitor.done();
 		} catch (Exception e) {
-			Trace.trace(Trace.SEVERE, "Could not save Tomcat v5.5 configuration to " + folder.toString(), e);
+			Trace.trace(Trace.SEVERE, "Could not save Tomcat v9.0 configuration to " + folder.toString(), e);
 			throw new CoreException(new Status(IStatus.ERROR, TomcatPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorCouldNotSaveConfiguration, new String[] {e.getLocalizedMessage()}), e));
 		}
 	}
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat90Handler.java b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat90Handler.java
index 01bd3a9..daf24fa 100644
--- a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat90Handler.java
+++ b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat90Handler.java
@@ -48,7 +48,7 @@
 	public List getRuntimeClasspath(IPath installPath, IPath configPath) {
 		List<IRuntimeClasspathEntry> cp = new ArrayList<IRuntimeClasspathEntry>();
 		
-		// 8.0 - add bootstrap.jar and tomcat-juli.jar from the Tomcat bin directory
+		// 9.0 - add bootstrap.jar and tomcat-juli.jar from the Tomcat bin directory
 		IPath binPath = installPath.append("bin");
 		if (binPath.toFile().exists()) {
 			IPath path = binPath.append("bootstrap.jar");
@@ -116,7 +116,7 @@
 				|| "3.0".equals(version) || "3.1".equals(version))
 			return Status.OK_STATUS;
 		
-		return new Status(IStatus.ERROR, TomcatPlugin.PLUGIN_ID, 0, Messages.errorSpec80, null);
+		return new Status(IStatus.ERROR, TomcatPlugin.PLUGIN_ID, 0, Messages.errorSpec90, null);
 	}
 
 	/**
@@ -145,7 +145,7 @@
 	 * @see ITomcatVersionHandler#prepareForServingDirectly(IPath, TomcatServer)
 	 */
 	public IStatus prepareForServingDirectly(IPath baseDir, TomcatServer server, String tomcatVersion) {
-		// Nothing beyond configuration required for Tomcat 8
+		// Nothing beyond configuration required for Tomcat 9
 		return Status.OK_STATUS;
 	}
 
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat90PublishModuleVisitor.java b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat90PublishModuleVisitor.java
index 9812c6f..f69aa33 100644
--- a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat90PublishModuleVisitor.java
+++ b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/Tomcat90PublishModuleVisitor.java
@@ -38,13 +38,13 @@
 public class Tomcat90PublishModuleVisitor extends TomcatPublishModuleVisitor {
 
 	/**
-	 * Instantiate a new Tomcat80PublishModuleVisitor
+	 * Instantiate a new Tomcat90PublishModuleVisitor
 	 * 
 	 * @param baseDir catalina base path
 	 * @param tomcatVersion tomcat version
 	 * @param serverInstance ServerInstance containing server.xml contents
 	 * @param sharedLoader string value for shared.loader catalina configuration property
-	 * @param enableMetaInfResources flag to indicate if Servlet 3.0 "META-INF/resources" feature should be supported
+	 * @param enableMetaInfResources flag to indicate if Servlet 3.0 or greater "META-INF/resources" feature should be supported
 	 */
 	Tomcat90PublishModuleVisitor(IPath baseDir, String tomcatVersion, ServerInstance serverInstance, String sharedLoader, boolean enableMetaInfResources) {
 		super(baseDir, tomcatVersion, serverInstance, sharedLoader, enableMetaInfResources);
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatPlugin.java b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatPlugin.java
index 5779f32..04b2bbd 100644
--- a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatPlugin.java
+++ b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatPlugin.java
@@ -42,8 +42,10 @@
 	public static final String TOMCAT_60 = "org.eclipse.jst.server.tomcat.60";
 	public static final String TOMCAT_70 = "org.eclipse.jst.server.tomcat.70";
 	public static final String TOMCAT_80 = "org.eclipse.jst.server.tomcat.80";
+	public static final String TOMCAT_85 = "org.eclipse.jst.server.tomcat.85";
 	public static final String TOMCAT_90 = "org.eclipse.jst.server.tomcat.90";
 
+	// Beyond 8.0, this verification approach is not effective and actually isn't currently used for 7.0 and beyond (see verifyInstallPath method).
 	protected static final String VERIFY_INSTALL_FILE = "verifyInstall.properties";
 	protected static VerifyResourceSpec[] verify32;
 	protected static VerifyResourceSpec[] verify40;
@@ -156,6 +158,8 @@
 			return new Tomcat70Handler();
 		else if (TOMCAT_80.equals(id))
 			return new Tomcat80Handler();
+		else if (TOMCAT_85.equals(id))
+			return new Tomcat85Handler();
 		else if (TOMCAT_90.equals(id))
 			return new Tomcat90Handler();
 		else
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatRuntime.java b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatRuntime.java
index 36630cb..cb2d5be 100644
--- a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatRuntime.java
+++ b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatRuntime.java
@@ -136,7 +136,7 @@
 		String id = getRuntime().getRuntimeType().getId();
 		if (!found) {
 			if (id != null && (id.indexOf("55") > 0 || id.indexOf("60") > 0 || id.indexOf("70") > 0 || id.indexOf("80") > 0
-					|| id.indexOf("90") > 0)) {
+					|| id.indexOf("85") > 0 || id.indexOf("90") > 0)) {
 				found = true;
 			}
 		}
@@ -193,6 +193,17 @@
 			}
 		}
 
+		// Else for Tomcat 8.5, ensure we have J2SE 7.0
+		else if (id != null && id.indexOf("85") > 0) {
+			IVMInstall vmInstall = getVMInstall();
+			if (vmInstall instanceof IVMInstall2) {
+				String javaVersion = ((IVMInstall2)vmInstall).getJavaVersion();
+				if (javaVersion != null && !isVMMinimumVersion(javaVersion, 107)) {
+					return new Status(IStatus.ERROR, TomcatPlugin.PLUGIN_ID, 0, Messages.errorJRETomcat85, null);
+				}
+			}
+		}
+
 		// Else for Tomcat 9.0, ensure we have J2SE 8.0
 		else if (id != null && id.indexOf("90") > 0) {
 			IVMInstall vmInstall = getVMInstall();
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatRuntimeClasspathProvider.java b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatRuntimeClasspathProvider.java
index 24f45c1..ab4d114 100644
--- a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatRuntimeClasspathProvider.java
+++ b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatRuntimeClasspathProvider.java
@@ -37,7 +37,7 @@
 		if (runtimeId.indexOf("32") > 0) {
 			IPath path = installPath.append("lib");
 			addLibraryEntries(list, path.toFile(), true);
-		} else if (runtimeId.indexOf("60") > 0 || runtimeId.indexOf("70") > 0 || runtimeId.indexOf("80") > 0) {
+		} else if (runtimeId.indexOf("60") > 0 || runtimeId.indexOf("70") > 0 || runtimeId.indexOf("80") > 0 || runtimeId.indexOf("85") > 0 || runtimeId.indexOf("90") > 0) {
 			// TODO May need some flexibility in case the installation has been configured differently
 			// This lib "simplification" may cause issues for some.
 			// Not known yet whether packaged Linux installs will go along.
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatRuntimeLocator.java b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatRuntimeLocator.java
index c36b784..3ab100c 100644
--- a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatRuntimeLocator.java
+++ b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatRuntimeLocator.java
@@ -33,6 +33,7 @@
 		"org.eclipse.jst.server.tomcat.runtime.60",
 		"org.eclipse.jst.server.tomcat.runtime.70",
 		"org.eclipse.jst.server.tomcat.runtime.80",
+		"org.eclipse.jst.server.tomcat.runtime.85",
 		"org.eclipse.jst.server.tomcat.runtime.90"};
 
 	/* (non-Javadoc)
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatServer.java b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatServer.java
index d9f15df..1753fb9 100644
--- a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatServer.java
+++ b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatServer.java
@@ -118,6 +118,8 @@
 					tcConfig = new Tomcat70Configuration(folder);
 				else if (id.indexOf("80") > 0)
 					tcConfig = new Tomcat80Configuration(folder);
+				else if (id.indexOf("85") > 0)
+					tcConfig = new Tomcat85Configuration(folder);
 				else if (id.indexOf("90") > 0)
 					tcConfig = new Tomcat90Configuration(folder);
 				else {
@@ -173,6 +175,8 @@
 			tcConfig = new Tomcat70Configuration(folder);
 		else if (id.indexOf("80") > 0)
 			tcConfig = new Tomcat80Configuration(folder);
+		else if (id.indexOf("85") > 0)
+			tcConfig = new Tomcat85Configuration(folder);
 		else if (id.indexOf("90") > 0)
 			tcConfig = new Tomcat90Configuration(folder);
 		else {
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatVersionHelper.java b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatVersionHelper.java
index de03528..02b8231 100644
--- a/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatVersionHelper.java
+++ b/plugins/org.eclipse.jst.server.tomcat.core/tomcatcore/org/eclipse/jst/server/tomcat/core/internal/TomcatVersionHelper.java
@@ -107,6 +107,7 @@
 		versionStringMap.put(TomcatPlugin.TOMCAT_60, "6.0.");
 		versionStringMap.put(TomcatPlugin.TOMCAT_70, "7.0.");
 		versionStringMap.put(TomcatPlugin.TOMCAT_80, "8.0.");
+		versionStringMap.put(TomcatPlugin.TOMCAT_85, "8.5.");
 		versionStringMap.put(TomcatPlugin.TOMCAT_90, "9.0.");
 	}
 
@@ -918,14 +919,19 @@
 
 			boolean modified = false;
 
-			boolean isTomcat8 = tomcatVersion.startsWith("8.");
+			boolean isTomcat80 = tomcatVersion.startsWith("8.0");
+			boolean isTomcat85 = tomcatVersion.startsWith("8.5");
 			boolean isTomcat9 = tomcatVersion.startsWith("9.");
 			// care about top-level modules only
 			TomcatPublishModuleVisitor visitor;
-			if (isTomcat8) {
+			if (isTomcat80) {
 				visitor = new Tomcat80PublishModuleVisitor(
 						baseDir, tomcatVersion, publishedInstance, loader, enableMetaInfResources);
 			}
+			else if (isTomcat85) {
+				visitor = new Tomcat85PublishModuleVisitor(
+						baseDir, tomcatVersion, publishedInstance, loader, enableMetaInfResources);
+			}
 			else if (isTomcat9) {
 				visitor = new Tomcat90PublishModuleVisitor(
 						baseDir, tomcatVersion, publishedInstance, loader, enableMetaInfResources);
@@ -1143,7 +1149,7 @@
 		File jarFile = null;
 		
 		if (TomcatPlugin.TOMCAT_60.equals(serverType) || TomcatPlugin.TOMCAT_70.equals(serverType) || TomcatPlugin.TOMCAT_80.equals(serverType)
-				|| TomcatPlugin.TOMCAT_90.equals(serverType)) {
+				|| TomcatPlugin.TOMCAT_85.equals(serverType) || TomcatPlugin.TOMCAT_90.equals(serverType)) {
 			catalinaJarPath = installPath.append("lib").append("catalina.jar");
 			jarFile = catalinaJarPath.toFile();
 			// If jar is not at expected location, try alternate location
diff --git a/plugins/org.eclipse.jst.server.tomcat.core/verifyInstall.properties b/plugins/org.eclipse.jst.server.tomcat.core/verifyInstall.properties
index 4522610..42f0886 100644
--- a/plugins/org.eclipse.jst.server.tomcat.core/verifyInstall.properties
+++ b/plugins/org.eclipse.jst.server.tomcat.core/verifyInstall.properties
@@ -19,4 +19,3 @@
 verify60install=lib/jasper-el.jar,lib/servlet-api.jar|[servletapi6].jar,bin/bootstrap.jar,conf,webapps
 verify70install=lib/jasper-el.jar,lib/servlet-api.jar|[servletapi6].jar,bin/bootstrap.jar,conf,webapps
 verify80install=lib/jasper-el.jar,lib/servlet-api.jar,lib/tomcat-websocket.jar,bin/bootstrap.jar,conf,webapps
-verify90install=lib/jasper-el.jar,lib/servlet-api.jar,bin/bootstrap.jar,conf,webapps
diff --git a/plugins/org.eclipse.jst.server.tomcat.ui/META-INF/MANIFEST.MF b/plugins/org.eclipse.jst.server.tomcat.ui/META-INF/MANIFEST.MF
index 4403207..f153818 100644
--- a/plugins/org.eclipse.jst.server.tomcat.ui/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.jst.server.tomcat.ui/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.jst.server.tomcat.ui; singleton:=true
-Bundle-Version: 1.1.500.qualifier
+Bundle-Version: 1.1.501.qualifier
 Bundle-Activator: org.eclipse.jst.server.tomcat.ui.internal.TomcatUIPlugin
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
diff --git a/plugins/org.eclipse.jst.server.tomcat.ui/plugin.xml b/plugins/org.eclipse.jst.server.tomcat.ui/plugin.xml
index 5776ea3..f411f64 100644
--- a/plugins/org.eclipse.jst.server.tomcat.ui/plugin.xml
+++ b/plugins/org.eclipse.jst.server.tomcat.ui/plugin.xml
@@ -36,6 +36,10 @@
          icon="icons/obj16/tomcat.gif"
          typeIds="org.eclipse.jst.server.tomcat.runtime.80"/>
       <image
+         id="org.eclipse.jst.server.tomcat.85"
+         icon="icons/obj16/tomcat.gif"
+         typeIds="org.eclipse.jst.server.tomcat.runtime.85"/>
+      <image
          id="org.eclipse.jst.server.tomcat.90"
          icon="icons/obj16/tomcat.gif"
          typeIds="org.eclipse.jst.server.tomcat.runtime.90"/>
@@ -73,6 +77,10 @@
          icon="icons/obj16/tomcat.gif"
          typeIds="org.eclipse.jst.server.tomcat.80"/>
       <image
+         id="org.eclipse.jst.server.tomcat.85"
+         icon="icons/obj16/tomcat.gif"
+         typeIds="org.eclipse.jst.server.tomcat.85"/>
+      <image
          id="org.eclipse.jst.server.tomcat.90"
          icon="icons/obj16/tomcat.gif"
          typeIds="org.eclipse.jst.server.tomcat.90"/>
@@ -170,6 +178,10 @@
          typeIds="org.eclipse.jst.server.tomcat.runtime.80"
          class="org.eclipse.jst.server.tomcat.ui.internal.TomcatRuntimeWizardFragment"/>
       <fragment
+         id="org.eclipse.jst.server.tomcat.runtime.85"
+         typeIds="org.eclipse.jst.server.tomcat.runtime.85"
+         class="org.eclipse.jst.server.tomcat.ui.internal.TomcatRuntimeWizardFragment"/>
+      <fragment
          id="org.eclipse.jst.server.tomcat.runtime.90"
          typeIds="org.eclipse.jst.server.tomcat.runtime.90"
          class="org.eclipse.jst.server.tomcat.ui.internal.TomcatRuntimeWizardFragment"/>
diff --git a/plugins/org.eclipse.jst.server.tomcat.ui/pom.xml b/plugins/org.eclipse.jst.server.tomcat.ui/pom.xml
index 590000b..419c77b 100644
--- a/plugins/org.eclipse.jst.server.tomcat.ui/pom.xml
+++ b/plugins/org.eclipse.jst.server.tomcat.ui/pom.xml
@@ -22,6 +22,6 @@
 

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

   <artifactId>org.eclipse.jst.server.tomcat.ui</artifactId>

-  <version>1.1.500-SNAPSHOT</version>

+  <version>1.1.501-SNAPSHOT</version>

   <packaging>eclipse-plugin</packaging>

 </project>