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 <[email protected]>
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: [email protected]
For additional commands, e-mail: [email protected]