Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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.

git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@1577182 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
markt-asf committed Mar 13, 2014
1 parent 4ff8248 commit 1f9b47e
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 46 deletions.
1 change: 1 addition & 0 deletions java/org/apache/catalina/manager/LocalStrings.properties
Expand Up @@ -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}
Expand Down
91 changes: 46 additions & 45 deletions java/org/apache/catalina/manager/ManagerServlet.java
Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -722,7 +724,6 @@ protected synchronized void save(PrintWriter writer, String path,
writer.println(smClient.getString(
"managerServlet.deployFailed", displayPath));
}

}


Expand All @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion java/org/apache/catalina/startup/HostConfig.java
Expand Up @@ -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;
}

Expand Down
8 changes: 8 additions & 0 deletions webapps/docs/changelog.xml
Expand Up @@ -112,6 +112,14 @@
<bug>56246</bug>: Fix NullPointerException in MemoryRealm when
authenticating an unknown user. (markt)
</fix>
<fix>
<bug>56248</bug>: 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)
</fix>
<fix>
<bug>56253</bug>: When listing resources that are provided by a JAR, fix
possible <code>StringIndexOutOfBoundsException</code>s. Add some unit
Expand Down

0 comments on commit 1f9b47e

Please sign in to comment.