You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by re...@apache.org on 2026/09/17 13:41:07 UTC
(tomcat) branch 10.1.x updated (e48ffad1db -> 75bdfd2e6a)
This is an automated email from the ASF dual-hosted git repository.
rmaucher pushed a change to branch 10.1.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
from e48ffad1db Fix three issues from review
new 4a51b8db52 Avoid saving some Context to server.xml
new 75bdfd2e6a Fix Java compat
The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
java/org/apache/catalina/core/StandardContext.java | 30 +++
.../apache/catalina/startup/ContextRuleSet.java | 37 ++++
.../catalina/storeconfig/LocalStrings.properties | 1 +
.../catalina/storeconfig/StandardContextSF.java | 15 +-
.../catalina/storeconfig/server-registry.xml | 1 +
.../catalina/storeconfig/TestStoreConfig.java | 243 +++++++++++++++++++++
webapps/docs/changelog.xml | 6 +
7 files changed, 330 insertions(+), 3 deletions(-)
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
(tomcat) 02/02: Fix Java compat
Posted by re...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rmaucher pushed a commit to branch 10.1.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 75bdfd2e6abe6b17927b2e8d2e16c73573bffb7b
Author: remm <re...@apache.org>
AuthorDate: Thu Sep 17 15:40:49 2026 +0200
Fix Java compat
---
java/org/apache/catalina/startup/ContextRuleSet.java | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/java/org/apache/catalina/startup/ContextRuleSet.java b/java/org/apache/catalina/startup/ContextRuleSet.java
index 8c29539c6d..973cbe12ff 100644
--- a/java/org/apache/catalina/startup/ContextRuleSet.java
+++ b/java/org/apache/catalina/startup/ContextRuleSet.java
@@ -209,7 +209,8 @@ final class SetDeployedFromServerXmlRule extends Rule {
@Override
public void begin(String namespace, String name, Attributes attributes) throws Exception {
- if (digester.peek() instanceof StandardContext context) {
+ if (digester.peek() instanceof StandardContext) {
+ StandardContext context = (StandardContext) digester.peek();
context.setDeployedFromServerXml(true);
if (digester.getLogger().isTraceEnabled()) {
digester.getLogger().trace("Calling StandardContext.setDeployedFromServerXml(true)");
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
(tomcat) 01/02: Avoid saving some Context to server.xml
Posted by re...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rmaucher pushed a commit to branch 10.1.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 4a51b8db52ea8bb187c361b287bca43d6ff37daf
Author: remm <re...@apache.org>
AuthorDate: Thu Sep 17 15:32:56 2026 +0200
Avoid saving some Context to server.xml
Use a marker flag to determine if it was deployed from server.xml in the
first place.
Co authored with OpenCode.
---
java/org/apache/catalina/core/StandardContext.java | 30 +++
.../apache/catalina/startup/ContextRuleSet.java | 36 +++
.../catalina/storeconfig/LocalStrings.properties | 1 +
.../catalina/storeconfig/StandardContextSF.java | 15 +-
.../catalina/storeconfig/server-registry.xml | 1 +
.../catalina/storeconfig/TestStoreConfig.java | 243 +++++++++++++++++++++
webapps/docs/changelog.xml | 6 +
7 files changed, 329 insertions(+), 3 deletions(-)
diff --git a/java/org/apache/catalina/core/StandardContext.java b/java/org/apache/catalina/core/StandardContext.java
index 8dd9a8d027..1690d4a558 100644
--- a/java/org/apache/catalina/core/StandardContext.java
+++ b/java/org/apache/catalina/core/StandardContext.java
@@ -270,6 +270,13 @@ public class StandardContext extends ContainerBase implements Context, Notificat
private boolean configured = false;
+ /**
+ * Indicates that this Context was deployed from a Context element defined in server.xml. The flag is for internal
+ * use only (it is not exposed via JMX and is not persisted by storeconfig).
+ */
+ private boolean deployedFromServerXml = false;
+
+
/**
* The security constraints for this web application.
*/
@@ -1564,6 +1571,29 @@ public class StandardContext extends ContainerBase implements Context, Notificat
}
+ /**
+ * Indicates whether this Context was deployed from a Context element defined in server.xml. The flag is set by the
+ * server.xml digester and is for internal use only. In particular, it is not exposed via JMX and is not stored by
+ * storeconfig.
+ *
+ * @return <code>true</code> if the Context element was parsed from server.xml
+ */
+ public boolean getDeployedFromServerXml() {
+ return this.deployedFromServerXml;
+ }
+
+
+ /**
+ * Sets the flag indicating that this Context was deployed from a Context element defined in server.xml. The flag is
+ * for internal use only. In particular, it is not exposed via JMX and is not stored by storeconfig.
+ *
+ * @param deployedFromServerXml The new flag value
+ */
+ public void setDeployedFromServerXml(boolean deployedFromServerXml) {
+ this.deployedFromServerXml = deployedFromServerXml;
+ }
+
+
@Override
public boolean getConfigured() {
return this.configured;
diff --git a/java/org/apache/catalina/startup/ContextRuleSet.java b/java/org/apache/catalina/startup/ContextRuleSet.java
index 6dccb9b6f0..8c29539c6d 100644
--- a/java/org/apache/catalina/startup/ContextRuleSet.java
+++ b/java/org/apache/catalina/startup/ContextRuleSet.java
@@ -16,8 +16,11 @@
*/
package org.apache.catalina.startup;
+import org.apache.catalina.core.StandardContext;
import org.apache.tomcat.util.digester.Digester;
+import org.apache.tomcat.util.digester.Rule;
import org.apache.tomcat.util.digester.RuleSet;
+import org.xml.sax.Attributes;
/**
* <strong>RuleSet</strong> for processing the contents of a Context definition element.
@@ -80,6 +83,7 @@ public class ContextRuleSet implements RuleSet {
if (create) {
digester.addObjectCreate(prefix + "Context", "org.apache.catalina.core.StandardContext", "className");
digester.addSetProperties(prefix + "Context");
+ digester.addRule(prefix + "Context", new SetDeployedFromServerXmlRule());
} else {
digester.addSetProperties(prefix + "Context", new String[] { "path", "docBase" });
}
@@ -189,3 +193,35 @@ public class ContextRuleSet implements RuleSet {
"org.apache.tomcat.util.http.CookieProcessor");
}
}
+
+
+/**
+ * A Rule that calls <code>setDeployedFromServerXml(true)</code> for the top object on the stack when a Context element
+ * is created, which only occurs for Context elements defined in server.xml. The flag allows storeconfig to detect a
+ * Context that is defined inline in server.xml so it is not moved to a separate configuration file when the
+ * configuration is stored.
+ */
+final class SetDeployedFromServerXmlRule extends Rule {
+
+ SetDeployedFromServerXmlRule() {
+ // NO-OP
+ }
+
+ @Override
+ public void begin(String namespace, String name, Attributes attributes) throws Exception {
+ if (digester.peek() instanceof StandardContext context) {
+ context.setDeployedFromServerXml(true);
+ if (digester.getLogger().isTraceEnabled()) {
+ digester.getLogger().trace("Calling StandardContext.setDeployedFromServerXml(true)");
+ }
+
+ StringBuilder code = digester.getGeneratedCode();
+ if (code != null) {
+ code.append(System.lineSeparator());
+ code.append(digester.toVariableName(context)).append(".setDeployedFromServerXml(true);");
+ code.append(System.lineSeparator());
+ }
+ }
+ }
+
+}
diff --git a/java/org/apache/catalina/storeconfig/LocalStrings.properties b/java/org/apache/catalina/storeconfig/LocalStrings.properties
index 280faefe5d..e26bf11e07 100644
--- a/java/org/apache/catalina/storeconfig/LocalStrings.properties
+++ b/java/org/apache/catalina/storeconfig/LocalStrings.properties
@@ -39,6 +39,7 @@ standardContextSF.canonicalPathError=Failed to obtain the canonical path of the
standardContextSF.moveFailed=Context original file at [{0}] is null, not a file or not writable
standardContextSF.nonFileConfigUrl=The config URL [{0}] is not file based
standardContextSF.storeContext=Store context [{0}] configuration separately at path [{1}]
+standardContextSF.storeContextInlineSkipped=Context [{0}] not stored because it is defined in server.xml and no writer for server.xml is available
standardContextSF.storeContextSkipped=Context [{0}] not stored because external context storage is not allowed and no writer for server.xml is available
standardContextSF.storeContextWithBackup=Store context [{0}] configuration separately with backup at path [{1}]
diff --git a/java/org/apache/catalina/storeconfig/StandardContextSF.java b/java/org/apache/catalina/storeconfig/StandardContextSF.java
index 5d64479b2e..e328a1c87e 100644
--- a/java/org/apache/catalina/storeconfig/StandardContextSF.java
+++ b/java/org/apache/catalina/storeconfig/StandardContextSF.java
@@ -54,7 +54,8 @@ import org.apache.tomcat.util.http.CookieProcessor;
* <li>Store a context that has an external configuration file to that file</li>
* <li>Store a context without an external configuration file to
* conf/enginename/hostname/context.xml, unless the registry allows inline
- * storage in server.xml</li>
+ * storage in server.xml and the context was deployed from a Context element
+ * in server.xml, in which case it is stored back inline to server.xml</li>
* <li>Store with backup</li>
* </ul>
*/
@@ -96,8 +97,10 @@ public class StandardContextSF extends StoreFactoryBase {
}
return;
}
- } else if (desc.isExternalOnly()) {
- // Set a configFile so that the configuration is actually saved
+ } else if (desc.isExternalOnly() || !((StandardContext) aContext).getDeployedFromServerXml()) {
+ // Set a configFile so that the configuration is actually saved. This only happens when the
+ // registry requires external storage or when the Context was not deployed from a Context element
+ // in server.xml (a Context defined in server.xml is stored back inline to server.xml instead).
Context context = ((StandardContext) aContext);
Host host = (Host) context.getParent();
File configBase = host.getConfigBaseFile();
@@ -111,6 +114,12 @@ public class StandardContextSF extends StoreFactoryBase {
storeContextSeparate(aWriter, indent, (StandardContext) aContext);
}
return;
+ } else if (aWriter == null) {
+ if (log.isInfoEnabled()) {
+ log.info(sm.getString("standardContextSF.storeContextInlineSkipped",
+ ((StandardContext) aContext).getPath()));
+ }
+ return;
}
}
}
diff --git a/java/org/apache/catalina/storeconfig/server-registry.xml b/java/org/apache/catalina/storeconfig/server-registry.xml
index b487a4e922..cfd405aa3a 100644
--- a/java/org/apache/catalina/storeconfig/server-registry.xml
+++ b/java/org/apache/catalina/storeconfig/server-registry.xml
@@ -70,6 +70,7 @@
<TransientAttribute>configured</TransientAttribute>
<TransientAttribute>displayName</TransientAttribute>
<TransientAttribute>distributable</TransientAttribute>
+ <TransientAttribute>deployedFromServerXml</TransientAttribute>
<TransientAttribute>domain</TransientAttribute>
<TransientAttribute>name</TransientAttribute>
<TransientAttribute>publicId</TransientAttribute>
diff --git a/test/org/apache/catalina/storeconfig/TestStoreConfig.java b/test/org/apache/catalina/storeconfig/TestStoreConfig.java
index c987a1ca84..e63c34a342 100644
--- a/test/org/apache/catalina/storeconfig/TestStoreConfig.java
+++ b/test/org/apache/catalina/storeconfig/TestStoreConfig.java
@@ -18,6 +18,7 @@ package org.apache.catalina.storeconfig;
import java.io.File;
import java.io.FileReader;
+import java.io.PrintWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
@@ -29,6 +30,7 @@ import org.junit.Assert;
import org.junit.Test;
import org.apache.catalina.Context;
+import org.apache.catalina.Host;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.realm.LockOutRealm;
@@ -313,4 +315,245 @@ public class TestStoreConfig extends TomcatBaseTest {
.parse(new InputSource(new StringReader(contextXmlDump)));
}
+ /**
+ * Verify that a Context parsed from a Context element in server.xml is flagged as deployed from server.xml, so
+ * storeconfig can detect it. The flag must also be set when server.xml is processed through the generated code
+ * path, so the generated code is checked as well.
+ *
+ * @throws Exception if the test experiences an unexpected error
+ */
+ @Test
+ public void testContextFromServerXmlIsFlagged() throws Exception {
+ File appDir = new File(getTemporaryDirectory(), "webapps/inline");
+ if (!appDir.mkdirs()) {
+ Assert.fail("Unable to create the webapp directory");
+ }
+
+ File conf = new File(getTemporaryDirectory(), "conf");
+ if (!conf.mkdirs()) {
+ Assert.fail("Unable to create conf directory");
+ }
+ addDeleteOnTearDown(conf);
+
+ File serverXml = new File(conf, "server.xml");
+ Files.write(serverXml.toPath(), String.join("\n",
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
+ "<Server port=\"-1\" shutdown=\"SHUTDOWN\">",
+ " <Service name=\"Catalina\">",
+ " <Engine name=\"Catalina\" defaultHost=\"localhost\">",
+ " <Host name=\"localhost\" appBase=\"webapps\"",
+ " deployOnStartup=\"false\" autoDeploy=\"false\">",
+ " <Context path=\"/inline\" docBase=\"inline\"/>",
+ " </Host>",
+ " </Engine>",
+ " </Service>",
+ "</Server>",
+ "").getBytes(StandardCharsets.UTF_8));
+
+ // Parse server.xml (with code generation enabled) without starting the server
+ File generatedCodeLocation = new File(getTemporaryDirectory(), "generated");
+ Catalina catalina = new Catalina();
+ catalina.load(new String[] { "start", "-generateCode", generatedCodeLocation.getAbsolutePath() });
+
+ Context inline = (Context) catalina.getServer().findServices()[0].getContainer().findChildren()[0]
+ .findChild("/inline");
+ Assert.assertNotNull("Context element from server.xml not found", inline);
+ Assert.assertTrue("Context from server.xml must be flagged as deployed from server.xml",
+ ((StandardContext) inline).getDeployedFromServerXml());
+
+ // The generated code must set the flag as well, so that contexts parsed through the generated code path are
+ // also flagged
+ File generatedClass = new File(generatedCodeLocation, "catalinaembedded/ServerXml.java");
+ Assert.assertTrue("Generated code was not created: " + generatedClass, generatedClass.exists());
+ String generatedCode;
+ try (FileReader reader = new FileReader(generatedClass);
+ StringWriter writer = new StringWriter()) {
+ IOTools.flow(reader, writer);
+ generatedCode = writer.toString();
+ }
+ Assert.assertTrue(generatedCode, generatedCode.contains(".setDeployedFromServerXml(true);"));
+ }
+
+ /**
+ * Verify that a context flagged as deployed from server.xml is stored back inline to the server.xml writer (and
+ * not moved to a new context configuration file) when inline storage is allowed (externalOnly is false).
+ *
+ * @throws Exception if the test experiences an unexpected error
+ */
+ @Test
+ public void testContextFromServerXmlStoredInline() throws Exception {
+ Tomcat tomcat = getTomcatInstance();
+ StoreConfigLifecycleListener storeConfigListener = new StoreConfigLifecycleListener();
+ tomcat.getServer().addLifecycleListener(storeConfigListener);
+
+ // Use a storable realm. The default embedded realm (Tomcat.SimpleRealm) is an inner class that the store
+ // path cannot instantiate a default instance of.
+ tomcat.getEngine().setRealm(new LockOutRealm());
+
+ File appDir = new File(getTemporaryDirectory(), "webapps/inline");
+ if (!appDir.mkdirs()) {
+ Assert.fail("Unable to create the webapp directory");
+ }
+ Context context = tomcat.addContext("/inline", appDir.getAbsolutePath());
+ ((StandardContext) context).setDeployedFromServerXml(true);
+
+ File conf = new File(getTemporaryDirectory(), "conf");
+ if (!conf.mkdirs()) {
+ Assert.fail("Unable to create conf directory");
+ }
+ addDeleteOnTearDown(conf);
+
+ tomcat.start();
+
+ IStoreConfig storeConfig = storeConfigListener.getStoreConfig();
+ StoreDescription desc = storeConfig.getRegistry().findDescription(StandardContext.class);
+ Assert.assertNotNull(desc);
+ boolean oldSeparate = desc.isStoreSeparate();
+ boolean oldExternalAllowed = desc.isExternalAllowed();
+ boolean oldExternalOnly = desc.isExternalOnly();
+ String serverXmlDump;
+ try {
+ desc.setStoreSeparate(true);
+ desc.setExternalAllowed(true);
+ desc.setExternalOnly(false);
+ StringWriter buffer = new StringWriter();
+ storeConfig.store(new PrintWriter(buffer), -2, tomcat.getServer());
+ serverXmlDump = buffer.toString();
+ } finally {
+ desc.setStoreSeparate(oldSeparate);
+ desc.setExternalAllowed(oldExternalAllowed);
+ desc.setExternalOnly(oldExternalOnly);
+ }
+
+ // The context must be stored inline in server.xml, without the internal flag attribute
+ Assert.assertTrue(serverXmlDump, serverXmlDump.contains("<Context"));
+ Assert.assertTrue(serverXmlDump, serverXmlDump.contains("path=\"/inline\""));
+ Assert.assertFalse(serverXmlDump, serverXmlDump.contains("deployedFromServerXml"));
+ // The stored configuration must remain well-formed
+ SAXParserFactory.newInstance().newSAXParser().getXMLReader()
+ .parse(new InputSource(new StringReader(serverXmlDump)));
+
+ // No new context configuration file must have been created
+ Host host = tomcat.getHost();
+ Assert.assertFalse(new File(host.getConfigBaseFile(), "inline.xml").exists());
+ }
+
+ /**
+ * Verify that a context that was not deployed from server.xml and that has no configuration file is stored to a
+ * new context configuration file even when inline storage is allowed (externalOnly is false).
+ *
+ * @throws Exception if the test experiences an unexpected error
+ */
+ @Test
+ public void testContextNotFromServerXmlStoredToNewFile() throws Exception {
+ Tomcat tomcat = getTomcatInstance();
+ StoreConfigLifecycleListener storeConfigListener = new StoreConfigLifecycleListener();
+ tomcat.getServer().addLifecycleListener(storeConfigListener);
+
+ // Use a storable realm. The default embedded realm (Tomcat.SimpleRealm) is an inner class that the store
+ // path cannot instantiate a default instance of.
+ tomcat.getEngine().setRealm(new LockOutRealm());
+
+ File appDir = new File(getTemporaryDirectory(), "webapps/standalone");
+ if (!appDir.mkdirs()) {
+ Assert.fail("Unable to create the webapp directory");
+ }
+ Context context = tomcat.addContext("/standalone", appDir.getAbsolutePath());
+ Assert.assertFalse("Programmatic context must not be flagged as deployed from server.xml",
+ ((StandardContext) context).getDeployedFromServerXml());
+
+ File conf = new File(getTemporaryDirectory(), "conf");
+ if (!conf.mkdirs()) {
+ Assert.fail("Unable to create conf directory");
+ }
+ addDeleteOnTearDown(conf);
+
+ tomcat.start();
+
+ IStoreConfig storeConfig = storeConfigListener.getStoreConfig();
+ StoreDescription desc = storeConfig.getRegistry().findDescription(StandardContext.class);
+ Assert.assertNotNull(desc);
+ boolean oldSeparate = desc.isStoreSeparate();
+ boolean oldExternalAllowed = desc.isExternalAllowed();
+ boolean oldExternalOnly = desc.isExternalOnly();
+ String serverXmlDump;
+ try {
+ desc.setStoreSeparate(true);
+ desc.setExternalAllowed(true);
+ desc.setExternalOnly(false);
+ StringWriter buffer = new StringWriter();
+ storeConfig.store(new PrintWriter(buffer), -2, tomcat.getServer());
+ serverXmlDump = buffer.toString();
+ } finally {
+ desc.setStoreSeparate(oldSeparate);
+ desc.setExternalAllowed(oldExternalAllowed);
+ desc.setExternalOnly(oldExternalOnly);
+ }
+
+ // The context must not be stored inline in server.xml
+ Assert.assertFalse(serverXmlDump, serverXmlDump.contains("standalone"));
+
+ // A new context configuration file must have been created instead
+ File contextXml = new File(tomcat.getHost().getConfigBaseFile(), "standalone.xml");
+ Assert.assertTrue("Context file was not created: " + contextXml, contextXml.exists());
+ String contextXmlDump;
+ try (FileReader reader = new FileReader(contextXml);
+ StringWriter writer = new StringWriter()) {
+ IOTools.flow(reader, writer);
+ contextXmlDump = writer.toString();
+ }
+ Assert.assertTrue(contextXmlDump, contextXmlDump.contains("<Context"));
+ // The stored configuration must remain well-formed
+ SAXParserFactory.newInstance().newSAXParser().getXMLReader()
+ .parse(new InputSource(new StringReader(contextXmlDump)));
+ }
+
+ /**
+ * Verify that storing a context flagged as deployed from server.xml with no writer for server.xml is skipped
+ * gracefully (no error, no new context configuration file).
+ *
+ * @throws Exception if the test experiences an unexpected error
+ */
+ @Test
+ public void testContextFromServerXmlStoreWithoutWriterSkipped() throws Exception {
+ Tomcat tomcat = getTomcatInstance();
+ StoreConfigLifecycleListener storeConfigListener = new StoreConfigLifecycleListener();
+ tomcat.getServer().addLifecycleListener(storeConfigListener);
+
+ File appDir = new File(getTemporaryDirectory(), "webapps/skipped");
+ if (!appDir.mkdirs()) {
+ Assert.fail("Unable to create the webapp directory");
+ }
+ Context context = tomcat.addContext("/skipped", appDir.getAbsolutePath());
+ ((StandardContext) context).setDeployedFromServerXml(true);
+
+ File conf = new File(getTemporaryDirectory(), "conf");
+ if (!conf.mkdirs()) {
+ Assert.fail("Unable to create conf directory");
+ }
+ addDeleteOnTearDown(conf);
+
+ tomcat.start();
+
+ IStoreConfig storeConfig = storeConfigListener.getStoreConfig();
+ StoreDescription desc = storeConfig.getRegistry().findDescription(StandardContext.class);
+ Assert.assertNotNull(desc);
+ boolean oldSeparate = desc.isStoreSeparate();
+ boolean oldExternalAllowed = desc.isExternalAllowed();
+ boolean oldExternalOnly = desc.isExternalOnly();
+ try {
+ desc.setStoreSeparate(true);
+ desc.setExternalAllowed(true);
+ desc.setExternalOnly(false);
+ // No writer available for server.xml and no config file: storing must be skipped without an error
+ desc.getStoreFactory().store(null, -2, context);
+ } finally {
+ desc.setStoreSeparate(oldSeparate);
+ desc.setExternalAllowed(oldExternalAllowed);
+ desc.setExternalOnly(oldExternalOnly);
+ }
+
+ Assert.assertFalse(new File(tomcat.getHost().getConfigBaseFile(), "skipped.xml").exists());
+ }
+
}
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 818c4c3d07..4fc2040122 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -130,6 +130,12 @@
layout of the existing file (comments, blank lines and attribute
order) on a best effort basis. (remm)
</update>
+ <fix>
+ Track in <code>StandardContext</code> whether the context was
+ deployed from a <code>Context</code> element in
+ <code>server.xml</code>. Use it to have <code>StoreConfig</code>
+ save to a new config file. (remm)
+ </fix>
</changelog>
</subsection>
</section>
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org