--- org/apache/catalina/startup/HostConfig.java	2021-01-01 00:00:00.000000000 +0000
+++ org/apache/catalina/startup/HostConfig.java.new	2021-01-01 00:00:00.000000000 +0000
@@ -16,6 +16,7 @@
  */
 package org.apache.catalina.startup;
 
+import java.io.Closeable;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
@@ -60,6 +61,7 @@
 import org.apache.catalina.LifecycleEvent;
 import org.apache.catalina.LifecycleListener;
 import org.apache.catalina.Manager;
+import org.apache.catalina.TomcatControllerHandler;
 import org.apache.catalina.core.StandardContext;
 import org.apache.catalina.core.StandardHost;
 import org.apache.catalina.security.DeployXmlPermission;
@@ -427,7 +429,7 @@
         deployWARs(appBase, filteredAppPaths);
         // Deploy expanded folders
         deployDirectories(appBase, filteredAppPaths);
-
+        TomcatControllerHandler.getTomcatController().deploySpecificApp(this, host, invalidWars, deployed, appBase, filteredAppPaths);
     }
 
 
@@ -785,7 +787,7 @@
     }
 
 
-    private boolean validateContextPath(File appBase, String contextPath) {
+    public boolean validateContextPath(File appBase, String contextPath) {
         // More complicated than the ideal as the canonical path may or may
         // not end with File.separator for a directory
 
@@ -821,12 +823,16 @@
         return canonicalDocBase.equals(docBase.toString());
     }
 
+    protected void deployWAR(ContextName cn, File war) {
+        deployWAR(cn, war, ".war");
+    }
+
     /**
      * Deploy packed WAR.
      * @param cn The context name
      * @param war The WAR file
      */
-    protected void deployWAR(ContextName cn, File war) {
+    protected void deployWAR(ContextName cn, File war, String extension) {
 
         File xml = new File(host.getAppBaseFile(),
                 cn.getBaseName() + "/" + Constants.ApplicationContextXml);
@@ -974,7 +980,7 @@
             context.setName(cn.getName());
             context.setPath(cn.getPath());
             context.setWebappVersion(cn.getVersion());
-            context.setDocBase(cn.getBaseName() + ".war");
+            context.setDocBase(cn.getBaseName() + "." + extension);
             host.addChild(context);
         } catch (Throwable t) {
             ExceptionUtils.handleThrowable(t);
@@ -1007,6 +1013,8 @@
             addGlobalRedeployResources(deployedApp);
         }
 
+        deployedApp.closeable = TomcatControllerHandler.getTomcatController().getCloseable();
+                
         deployed.put(cn.getName(), deployedApp);
 
         if (log.isInfoEnabled()) {
@@ -1193,7 +1201,7 @@
      * @param contextName of the context which will be checked
      * @return <code>true</code> if the specified deployment exists
      */
-    protected boolean deploymentExists(String contextName) {
+    public boolean deploymentExists(String contextName) {
         return (deployed.containsKey(contextName) ||
                 (host.findChild(contextName) != null));
     }
@@ -1428,7 +1436,16 @@
             log.warn(sm.getString
                      ("hostConfig.context.remove", app.name), t);
         }
-        deployed.remove(app.name);
+        DeployedApplication undeployedApplication = deployed.remove(app.name);
+        Closeable closeable = undeployedApplication.closeable;
+        if (closeable != null) {
+            try {
+                closeable.close();
+            } catch (IOException e) {
+                // ignore
+            }
+            TomcatControllerHandler.getTomcatController().warUndeployed(closeable);
+        }
     }
 
 
@@ -1762,7 +1779,7 @@
      * This class represents the state of a deployed application, as well as
      * the monitored resources.
      */
-    protected static class DeployedApplication {
+    public static class DeployedApplication {
         public DeployedApplication(String name, boolean hasDescriptor) {
             this.name = name;
             this.hasDescriptor = hasDescriptor;
@@ -1811,6 +1828,8 @@
          * run of the auto deployer.
          */
         public boolean loggedDirWarning = false;
+        
+        public Closeable closeable;
     }
 
     private static class DeployDescriptor implements Runnable {
@@ -1832,7 +1851,7 @@
         }
     }
 
-    private static class DeployWar implements Runnable {
+    public static class DeployWar implements Runnable {
 
         private HostConfig config;
         private ContextName cn;
@@ -1846,7 +1865,11 @@
 
         @Override
         public void run() {
-            config.deployWAR(cn, war);
+            try {
+                config.deployWAR(cn, war, cn.getExtension());
+            } finally {
+                TomcatControllerHandler.getTomcatController().warDeployed();
+            }
         }
     }
 
