diff --git a/java/org/apache/catalina/manager/LocalStrings.properties b/java/org/apache/catalina/manager/LocalStrings.properties index 8ee69ac05899..b0b397263ed5 100644 --- a/java/org/apache/catalina/manager/LocalStrings.properties +++ b/java/org/apache/catalina/manager/LocalStrings.properties @@ -80,6 +80,7 @@ managerServlet.exception=FAIL - Encountered exception {0} managerServlet.findleaksFail=FAIL - Find leaks failed: Host not instance of StandardHost managerServlet.findleaksList=OK - Found potential memory leaks in the following applications: managerServlet.findleaksNone=OK - No memory leaks found +managerServlet.invalidCommand=FAIL - Invalid parameters supplied for command [{0}] managerServlet.invalidPath=FAIL - Invalid context path {0} was specified managerServlet.listed=OK - Listed applications for virtual host {0} managerServlet.listitem={0}:{1}:{2}:{3} diff --git a/java/org/apache/catalina/manager/ManagerServlet.java b/java/org/apache/catalina/manager/ManagerServlet.java index b2aecea0e8f5..3e19bbbe5906 100644 --- a/java/org/apache/catalina/manager/ManagerServlet.java +++ b/java/org/apache/catalina/manager/ManagerServlet.java @@ -54,6 +54,7 @@ import org.apache.catalina.connector.Connector; import org.apache.catalina.core.StandardHost; import org.apache.catalina.core.StandardServer; +import org.apache.catalina.startup.ExpandWar; import org.apache.catalina.util.ContextName; import org.apache.catalina.util.RequestUtil; import org.apache.catalina.util.ServerInfo; @@ -179,8 +180,7 @@ public class ManagerServlet extends HttpServlet implements ContainerServlet { /** * File object representing the directory into which the deploy() command - * will store the WAR and context configuration files that have been - * uploaded. + * will deploy uploaded WAR files (normally the appBase). */ protected File deployed = null; @@ -340,8 +340,11 @@ public void doGet(HttpServletRequest request, } else if (command.equals("/deploy")) { if (war != null || config != null) { deploy(writer, config, cn, war, update, smClient); - } else { + } else if (tag != null) { deploy(writer, cn, tag, smClient); + } else { + writer.println(smClient.getString( + "managerServlet.invalidCommand", command)); } } else if (command.equals("/list")) { list(writer, smClient); @@ -654,21 +657,16 @@ protected synchronized void save(PrintWriter writer, String path, String baseName = cn.getBaseName(); String displayPath = cn.getDisplayName(); - // Check if app already exists, or undeploy it if updating + // If app exists deployment can only proceed if update is true + // Note existing WAR will be deleted and then replaced Context context = (Context) host.findChild(name); - if (update) { - if (context != null) { - undeploy(writer, cn, smClient); - } - context = (Context) host.findChild(name); - } - if (context != null) { + if (context != null && !update) { writer.println(smClient.getString("managerServlet.alreadyContext", displayPath)); return; } - // Calculate the base path + // Determine directory where WAR will be uploaded to File deployedPath = deployed; if (tag != null) { deployedPath = new File(versioned, tag); @@ -679,26 +677,30 @@ protected synchronized void save(PrintWriter writer, String path, } } - // Upload the web application archive to a local WAR file + // Determine full path for uploaded WAR File localWar = new File(deployedPath, baseName + ".war"); if (debug >= 2) { log("Uploading WAR file to " + localWar); } - // Copy WAR to appBase try { if (!isServiced(name)) { addServiced(name); try { + if (update && tag == null && localWar.isFile()) { + if (!localWar.delete()) { + writer.println(smClient.getString("managerServlet.deleteFail", + localWar)); + return; + } + } // Upload WAR uploadWar(writer, request, localWar, smClient); - // Copy WAR and XML to the host app base if needed if (tag != null) { + // Copy WAR to the host's appBase deployedPath = deployed; File localWarCopy = new File(deployedPath, baseName + ".war"); copy(localWar, localWarCopy); - localWar = localWarCopy; - copy(localWar, new File(host.getAppBaseFile(), baseName + ".war")); } // Perform new deployment check(name); @@ -722,7 +724,6 @@ protected synchronized void save(PrintWriter writer, String path, writer.println(smClient.getString( "managerServlet.deployFailed", displayPath)); } - } @@ -738,6 +739,8 @@ protected synchronized void save(PrintWriter writer, String path, protected void deploy(PrintWriter writer, ContextName cn, String tag, StringManager smClient) { + // NOTE: It is assumed that update is always true in this method. + // Validate the requested context path if (!validateContextName(cn, writer, smClient)) { return; @@ -747,26 +750,19 @@ protected void deploy(PrintWriter writer, ContextName cn, String tag, String name = cn.getName(); String displayPath = cn.getDisplayName(); - // Calculate the base path - File deployedPath = versioned; - if (tag != null) { - deployedPath = new File(deployedPath, tag); - } - // Find the local WAR file - File localWar = new File(deployedPath, baseName + ".war"); - - // Check if app already exists, or undeploy it if updating - Context context = (Context) host.findChild(name); - if (context != null) { - undeploy(writer, cn, smClient); - } + File localWar = new File(versioned, baseName + ".war"); // Copy WAR to appBase try { if (!isServiced(name)) { addServiced(name); try { + if (!localWar.delete()) { + writer.println(smClient.getString("managerServlet.deleteFail", + localWar)); + return; + } copy(localWar, new File(host.getAppBaseFile(), baseName + ".war")); // Perform new deployment check(name); @@ -842,15 +838,10 @@ protected void deploy(PrintWriter writer, String config, ContextName cn, String baseName = cn.getBaseName(); String displayPath = cn.getDisplayName(); - // Check if app already exists, or undeploy it if updating + // If app exists deployment can only proceed if update is true + // Note existing files will be deleted and then replaced Context context = (Context) host.findChild(name); - if (update) { - if (context != null) { - undeploy(writer, cn, smClient); - } - context = (Context) host.findChild(name); - } - if (context != null) { + if (context != null && !update) { writer.println(smClient.getString("managerServlet.alreadyContext", displayPath)); return; @@ -873,17 +864,27 @@ protected void deploy(PrintWriter writer, String config, ContextName cn, "managerServlet.mkdirFail",configBase)); return; } - copy(new File(config), - new File(configBase, baseName + ".xml")); + File localConfig = new File(configBase, baseName + ".xml"); + if (localConfig.isFile() && !localConfig.delete()) { + writer.println(smClient.getString( + "managerServlet.deleteFail", localConfig)); + return; + } + copy(new File(config), localConfig); } if (war != null) { + File localWar; if (war.endsWith(".war")) { - copy(new File(war), - new File(host.getAppBaseFile(), baseName + ".war")); + localWar = new File(host.getAppBaseFile(), baseName + ".war"); } else { - copy(new File(war), - new File(host.getAppBaseFile(), baseName)); + localWar = new File(host.getAppBaseFile(), baseName); + } + if (localWar.exists() && !ExpandWar.delete(localWar)) { + writer.println(smClient.getString( + "managerServlet.deleteFail", localWar)); + return; } + copy(new File(war), localWar); } // Perform new deployment check(name); diff --git a/java/org/apache/catalina/startup/HostConfig.java b/java/org/apache/catalina/startup/HostConfig.java index 64c7af24be27..d785700eb854 100644 --- a/java/org/apache/catalina/startup/HostConfig.java +++ b/java/org/apache/catalina/startup/HostConfig.java @@ -445,7 +445,7 @@ protected void deployApps(String name) { ContextName cn = new ContextName(name, false); String baseName = cn.getBaseName(); - if (deploymentExists(baseName)) { + if (deploymentExists(cn.getName())) { return; } diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index ddde8a9e75e7..c69ebc817bbf 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -112,6 +112,14 @@ 56246: Fix NullPointerException in MemoryRealm when authenticating an unknown user. (markt) + + 56248: Allow the deployer to update an existing WAR file + without undeploying the existing application if the update flag is set. + This allows any existing custom context.xml for the application to be + retained. To update an application and remove any existing context.xml + simply undeploy the old version of the application before deploying the + new version. (markt) + 56253: When listing resources that are provided by a JAR, fix possible StringIndexOutOfBoundsExceptions. Add some unit