You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2015/04/01 19:05:16 UTC
svn commit: r1670730 -
/tomcat/trunk/java/org/apache/catalina/startup/HostConfig.java
Author: markt
Date: Wed Apr 1 17:05:16 2015
New Revision: 1670730
URL: http://svn.apache.org/r1670730
Log:
Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=57772
When reloading an application and a DIR representing an expanded WAR needs to be deleted ensure that the DIR is deleted after the context has been stopped rather than before.
Modified:
tomcat/trunk/java/org/apache/catalina/startup/HostConfig.java
Modified: tomcat/trunk/java/org/apache/catalina/startup/HostConfig.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/HostConfig.java?rev=1670730&r1=1670729&r2=1670730&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/startup/HostConfig.java (original)
+++ tomcat/trunk/java/org/apache/catalina/startup/HostConfig.java Wed Apr 1 17:05:16 2015
@@ -1264,12 +1264,10 @@ public class HostConfig implements Lifec
docBaseFile = new File(host.getAppBaseFile(),
docBase);
}
- ExpandWar.delete(docBaseFile);
- // Reset the docBase to trigger re-expansion of the
- // WAR
- context.setDocBase(resource.getAbsolutePath());
+ reload(app, docBaseFile, resource.getAbsolutePath());
+ } else {
+ reload(app, null, null);
}
- reload(app);
// Update times
app.redeployResources.put(resources[i],
Long.valueOf(resource.lastModified()));
@@ -1331,7 +1329,7 @@ public class HostConfig implements Lifec
update) {
if (!update) {
// Reload application
- reload(app);
+ reload(app, null, null);
update = true;
}
// Update times. More than one file may have been updated. We
@@ -1344,16 +1342,28 @@ public class HostConfig implements Lifec
}
- private void reload(DeployedApplication app) {
+ /*
+ * Note: If either of fileToRemove and newDocBase are null, both will be
+ * ignored.
+ */
+ private void reload(DeployedApplication app, File fileToRemove, String newDocBase) {
if(log.isInfoEnabled())
log.info(sm.getString("hostConfig.reload", app.name));
Context context = (Context) host.findChild(app.name);
if (context.getState().isAvailable()) {
+ if (fileToRemove != null && newDocBase != null) {
+ context.addLifecycleListener(
+ new ExpandedDirectoryRemovalListener(fileToRemove, newDocBase));
+ }
// Reload catches and logs exceptions
context.reload();
} else {
// If the context was not started (for example an error
// in web.xml) we'll still get to try to start
+ if (fileToRemove != null && newDocBase != null) {
+ ExpandWar.delete(fileToRemove);
+ context.setDocBase(newDocBase);
+ }
try {
context.start();
} catch (Exception e) {
@@ -1772,4 +1782,54 @@ public class HostConfig implements Lifec
config.deployDirectory(cn, dir);
}
}
+
+
+ /*
+ * The purpose of this class is to provide a way for HostConfig to get
+ * a Context to delete an expanded WAR after the Context stops. This is to
+ * resolve this issue described in Bug 57772. The alternative solutions
+ * require either duplicating a lot of the Context.reload() code in
+ * HostConfig or adding a new reload(boolean) method to Context that allows
+ * the caller to optionally delete any expanded WAR.
+ *
+ * The LifecycleListener approach offers greater flexibility and enables the
+ * behaviour to be changed / extended / removed in future without changing
+ * the Context API.
+ */
+ private static class ExpandedDirectoryRemovalListener implements LifecycleListener {
+
+ private final File toDelete;
+ private final String newDocBase;
+
+ /**
+ * Create a listener that will ensure that any expanded WAR is removed
+ * and the docBase set to the specified WAR.
+ *
+ * @param toDelete The file (a directory representing an expanded WAR)
+ * to be deleted
+ * @param newDocBase The new docBase for the Context
+ */
+ public ExpandedDirectoryRemovalListener(File toDelete, String newDocBase) {
+ this.toDelete = toDelete;
+ this.newDocBase = newDocBase;
+ }
+
+ @Override
+ public void lifecycleEvent(LifecycleEvent event) {
+ if (event.getType() == Lifecycle.AFTER_STOP_EVENT) {
+ // The context has stopped.
+ Context context = (Context) event.getLifecycle();
+
+ // Remove the old expanded WAR.
+ ExpandWar.delete(toDelete);
+
+ // Reset the docBase to trigger re-expansion of the WAR.
+ context.setDocBase(newDocBase);
+
+ // Remove this listener from the Context else it will run every
+ // time the Context is stopped.
+ context.removeLifecycleListener(this);
+ }
+ }
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org