This is an automated email from the ASF dual-hosted git repository. remm pushed a commit to branch 11.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/11.0.x by this push: new 4d11acc4a4 Allow readOnly attribute configuration on the Resources 4d11acc4a4 is described below commit 4d11acc4a4dd9762477882683f8b202a7238b8b5 Author: remm <r...@apache.org> AuthorDate: Mon Dec 23 11:08:09 2024 +0100 Allow readOnly attribute configuration on the Resources Use the exposed attribute value in the default and WebDAV Servlets in addition to the existing readOnly configuration. --- java/org/apache/catalina/WebResourceRoot.java | 17 +++++++++++++++++ .../org/apache/catalina/servlets/DefaultServlet.java | 18 ++++++++++++++---- java/org/apache/catalina/servlets/WebdavServlet.java | 20 ++++++++++---------- .../apache/catalina/webresources/DirResourceSet.java | 9 ++++++--- .../apache/catalina/webresources/StandardRoot.java | 12 ++++++++++++ webapps/docs/changelog.xml | 7 +++++++ webapps/docs/config/resources.xml | 6 ++++++ 7 files changed, 72 insertions(+), 17 deletions(-) diff --git a/java/org/apache/catalina/WebResourceRoot.java b/java/org/apache/catalina/WebResourceRoot.java index fb6b43c002..f96dc7d7e8 100644 --- a/java/org/apache/catalina/WebResourceRoot.java +++ b/java/org/apache/catalina/WebResourceRoot.java @@ -414,6 +414,23 @@ public interface WebResourceRoot extends Lifecycle { // NO-OP } + /** + * Set if the main resources are read only. + * + * @param readOnly the value + */ + default void setReadOnly(boolean readOnly) { + // NO-OP + } + + /** + * @return {@code true} if the main resources are read only, otherwise {@code false}. The default implementation + * returns {@code false}. + */ + default boolean isReadOnly() { + return false; + } + enum ResourceSetType { PRE, RESOURCE_JAR, diff --git a/java/org/apache/catalina/servlets/DefaultServlet.java b/java/org/apache/catalina/servlets/DefaultServlet.java index 808f90ad23..1c56e31f26 100644 --- a/java/org/apache/catalina/servlets/DefaultServlet.java +++ b/java/org/apache/catalina/servlets/DefaultServlet.java @@ -493,6 +493,16 @@ public class DefaultServlet extends HttpServlet { } + protected boolean isListings() { + return listings; + } + + + protected boolean isReadOnly() { + return readOnly || resources.isReadOnly(); + } + + @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { @@ -555,7 +565,7 @@ public class DefaultServlet extends HttpServlet { allow.append("OPTIONS, GET, HEAD, POST"); // PUT and DELETE depend on readonly - if (!readOnly) { + if (!isReadOnly()) { allow.append(", PUT, DELETE"); } @@ -584,7 +594,7 @@ public class DefaultServlet extends HttpServlet { @Override protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - if (readOnly) { + if (isReadOnly()) { sendNotAllowed(req, resp); return; } @@ -707,7 +717,7 @@ public class DefaultServlet extends HttpServlet { @Override protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - if (readOnly) { + if (isReadOnly()) { sendNotAllowed(req, resp); return; } @@ -919,7 +929,7 @@ public class DefaultServlet extends HttpServlet { // Skip directory listings if we have been configured to // suppress them - if (!listings) { + if (!isListings()) { response.sendError(HttpServletResponse.SC_NOT_FOUND, sm.getString("defaultServlet.missingResource", request.getRequestURI())); return; diff --git a/java/org/apache/catalina/servlets/WebdavServlet.java b/java/org/apache/catalina/servlets/WebdavServlet.java index c7f7cfad55..6495685a73 100644 --- a/java/org/apache/catalina/servlets/WebdavServlet.java +++ b/java/org/apache/catalina/servlets/WebdavServlet.java @@ -751,7 +751,7 @@ public class WebdavServlet extends DefaultServlet implements PeriodicEventListen // if the resource does not exist. StringBuilder methodsAllowed = new StringBuilder("OPTIONS, GET, POST, HEAD"); - if (!readOnly) { + if (!isReadOnly()) { methodsAllowed.append(", DELETE"); if (!resource.isDirectory()) { methodsAllowed.append(", PUT"); @@ -765,7 +765,7 @@ public class WebdavServlet extends DefaultServlet implements PeriodicEventListen methodsAllowed.append(", LOCK, UNLOCK, PROPPATCH, COPY, MOVE"); - if (listings) { + if (isListings()) { methodsAllowed.append(", PROPFIND"); } @@ -796,7 +796,7 @@ public class WebdavServlet extends DefaultServlet implements PeriodicEventListen */ protected void doPropfind(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - if (!listings) { + if (!isListings()) { sendNotAllowed(req, resp); return; } @@ -1013,7 +1013,7 @@ public class WebdavServlet extends DefaultServlet implements PeriodicEventListen return; } - if (readOnly) { + if (isReadOnly()) { resp.sendError(WebdavStatus.SC_FORBIDDEN); return; } @@ -1194,7 +1194,7 @@ public class WebdavServlet extends DefaultServlet implements PeriodicEventListen return; } - if (readOnly) { + if (isReadOnly()) { resp.sendError(WebdavStatus.SC_FORBIDDEN); return; } @@ -1221,7 +1221,7 @@ public class WebdavServlet extends DefaultServlet implements PeriodicEventListen @Override protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - if (readOnly) { + if (isReadOnly()) { sendNotAllowed(req, resp); return; } @@ -1268,7 +1268,7 @@ public class WebdavServlet extends DefaultServlet implements PeriodicEventListen */ protected void doCopy(HttpServletRequest req, HttpServletResponse resp) throws IOException { - if (readOnly) { + if (isReadOnly()) { resp.sendError(WebdavStatus.SC_FORBIDDEN); return; } @@ -1289,7 +1289,7 @@ public class WebdavServlet extends DefaultServlet implements PeriodicEventListen */ protected void doMove(HttpServletRequest req, HttpServletResponse resp) throws IOException { - if (readOnly) { + if (isReadOnly()) { resp.sendError(WebdavStatus.SC_FORBIDDEN); return; } @@ -1318,7 +1318,7 @@ public class WebdavServlet extends DefaultServlet implements PeriodicEventListen */ protected void doLock(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - if (readOnly) { + if (isReadOnly()) { resp.sendError(WebdavStatus.SC_FORBIDDEN); return; } @@ -1731,7 +1731,7 @@ public class WebdavServlet extends DefaultServlet implements PeriodicEventListen */ protected void doUnlock(HttpServletRequest req, HttpServletResponse resp) throws IOException { - if (readOnly) { + if (isReadOnly()) { resp.sendError(WebdavStatus.SC_FORBIDDEN); return; } diff --git a/java/org/apache/catalina/webresources/DirResourceSet.java b/java/org/apache/catalina/webresources/DirResourceSet.java index f1d4e86199..026c61a065 100644 --- a/java/org/apache/catalina/webresources/DirResourceSet.java +++ b/java/org/apache/catalina/webresources/DirResourceSet.java @@ -101,13 +101,14 @@ public class DirResourceSet extends AbstractFileResourceSet implements WebResour checkPath(path); String webAppMount = getWebAppMount(); WebResourceRoot root = getRoot(); + boolean readOnly = isReadOnly(); if (path.startsWith(webAppMount)) { /* * Lock the path for reading until the WebResource has been constructed. The lock prevents concurrent reads * and writes (e.g. HTTP GET and PUT / DELETE) for the same path causing corruption of the FileResource * where some of the fields are set as if the file exists and some as set as if it does not. */ - ResourceLock lock = lockForRead(path); + ResourceLock lock = readOnly ? null : lockForRead(path); try { File f = file(path.substring(webAppMount.length()), false); if (f == null) { @@ -119,9 +120,11 @@ public class DirResourceSet extends AbstractFileResourceSet implements WebResour if (f.isDirectory() && path.charAt(path.length() - 1) != '/') { path = path + '/'; } - return new FileResource(root, path, f, isReadOnly(), getManifest(), this, lock.key); + return new FileResource(root, path, f, readOnly, getManifest(), this, readOnly ? null : lock.key); } finally { - unlockForRead(lock); + if (!readOnly) { + unlockForRead(lock); + } } } else { return new EmptyResource(root, path); diff --git a/java/org/apache/catalina/webresources/StandardRoot.java b/java/org/apache/catalina/webresources/StandardRoot.java index 2cb98e277a..7c5c08dbea 100644 --- a/java/org/apache/catalina/webresources/StandardRoot.java +++ b/java/org/apache/catalina/webresources/StandardRoot.java @@ -67,6 +67,7 @@ public class StandardRoot extends LifecycleMBeanBase implements WebResourceRoot private Context context; private boolean allowLinking = false; + private boolean readOnly = false; private final List<WebResourceSet> preResources = new ArrayList<>(); private WebResourceSet main; private final List<WebResourceSet> classResources = new ArrayList<>(); @@ -657,6 +658,16 @@ public class StandardRoot extends LifecycleMBeanBase implements WebResourceRoot } + @Override + public boolean isReadOnly() { + return (readOnly || main == null || main.isReadOnly()); + } + + @Override + public void setReadOnly(boolean readOnly) { + this.readOnly = readOnly; + } + // ----------------------------------------------------------- JMX Lifecycle @Override protected String getDomainInternal() { @@ -743,6 +754,7 @@ public class StandardRoot extends LifecycleMBeanBase implements WebResourceRoot } if (f.isDirectory()) { mainResourceSet = new DirResourceSet(this, "/", f.getAbsolutePath(), "/"); + mainResourceSet.setReadOnly(readOnly); } else if (f.isFile() && docBase.endsWith(".war")) { mainResourceSet = new WarResourceSet(this, "/", f.getAbsolutePath()); } else { diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index 2d9b8bf288..07a2246f93 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -116,6 +116,13 @@ Improve HTTP If headers processing according to RFC 9110. Based on pull request <pr>796</pr> by Chenjp. (remm/markt) </update> + <update> + Allow <code>readOnly</code> attribute configuration on the + <code>Resources</code> element and allow configure the + <code>readOnly</code> attribute value of the main resources. The + attribute value will also be used by the default and WebDAV Servlets. + (remm) + </update> </changelog> </subsection> <subsection name="Coyote"> diff --git a/webapps/docs/config/resources.xml b/webapps/docs/config/resources.xml index 4bad617355..ef6a3aec37 100644 --- a/webapps/docs/config/resources.xml +++ b/webapps/docs/config/resources.xml @@ -122,6 +122,12 @@ used.</p> </attribute> + <attribute name="readOnly" required="false"> + <p>If the value of this flag is <code>true</code>, then writing will + be enabled on the main resource set. The default value is + <code>false</code>.</p> + </attribute> + <attribute name="trackLockedFiles" required="false"> <p>Controls whether the track locked files feature is enabled. If enabled, all calls to methods that return objects that lock a file and --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org