This is an automated email from the ASF dual-hosted git repository. remm pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/9.0.x by this push: new 88674ee12a Allow readOnly attribute configuration on the Resources 88674ee12a is described below commit 88674ee12ae43b85e364916d7b9f8a607c05ed83 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 a4254fa574..60597be603 100644 --- a/java/org/apache/catalina/servlets/DefaultServlet.java +++ b/java/org/apache/catalina/servlets/DefaultServlet.java @@ -503,6 +503,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 { @@ -565,7 +575,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"); } @@ -594,7 +604,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; } @@ -717,7 +727,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; } @@ -929,7 +939,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 cd0401b0f5..15168ff499 100644 --- a/java/org/apache/catalina/servlets/WebdavServlet.java +++ b/java/org/apache/catalina/servlets/WebdavServlet.java @@ -750,7 +750,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"); @@ -764,7 +764,7 @@ public class WebdavServlet extends DefaultServlet implements PeriodicEventListen methodsAllowed.append(", LOCK, UNLOCK, PROPPATCH, COPY, MOVE"); - if (listings) { + if (isListings()) { methodsAllowed.append(", PROPFIND"); } @@ -795,7 +795,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; } @@ -1012,7 +1012,7 @@ public class WebdavServlet extends DefaultServlet implements PeriodicEventListen return; } - if (readOnly) { + if (isReadOnly()) { resp.sendError(WebdavStatus.SC_FORBIDDEN); return; } @@ -1193,7 +1193,7 @@ public class WebdavServlet extends DefaultServlet implements PeriodicEventListen return; } - if (readOnly) { + if (isReadOnly()) { resp.sendError(WebdavStatus.SC_FORBIDDEN); return; } @@ -1220,7 +1220,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; } @@ -1267,7 +1267,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; } @@ -1288,7 +1288,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; } @@ -1317,7 +1317,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; } @@ -1730,7 +1730,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 ca9944cbd5..55ff6d1a91 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