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 2021/09/23 21:18:33 UTC

[tomcat] branch main updated (5d47c04 -> 37bc60c)

This is an automated email from the ASF dual-hosted git repository.

markt pushed a change to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git.


    from 5d47c04  Fix incorrect indent
     new 0d421d6  Servlet API changes required to support errorOnELNotFound
     new f6d14bb  JSP API updates required to implement errorOnELNotFound
     new 37bc60c  Implement the new page/tag directive errorOnELNotFound

The 3 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:
 .../descriptor/JspPropertyGroupDescriptor.java     |   8 ++
 .../jakarta/servlet/jsp/LocalStrings.properties    |   2 +-
 .../jakarta/servlet/jsp/el/NotFoundELResolver.java |  24 +++-
 java/jakarta/servlet/jsp/resources/jspxml.dtd      |  27 ++--
 java/jakarta/servlet/jsp/resources/jspxml.xsd      |   1 +
 java/org/apache/jasper/compiler/Compiler.java      |   4 +
 java/org/apache/jasper/compiler/Generator.java     |  15 +++
 java/org/apache/jasper/compiler/JspConfig.java     |  21 ++-
 java/org/apache/jasper/compiler/PageInfo.java      |  40 ++++++
 .../apache/jasper/compiler/TagFileProcessor.java   |   3 +-
 java/org/apache/jasper/compiler/Validator.java     |  15 +++
 .../jasper/resources/LocalStrings.properties       |   4 +
 .../apache/jasper/runtime/JspContextWrapper.java   |   9 ++
 .../jasper/runtime/JspSourceDirectives.java}       |  12 +-
 .../org/apache/jasper/runtime/PageContextImpl.java |   6 +
 .../util/descriptor/web/JspPropertyGroup.java      |   6 +
 .../web/JspPropertyGroupDescriptorImpl.java        |  12 ++
 .../tomcat/util/descriptor/web/WebRuleSet.java     |   2 +
 test/org/apache/jasper/compiler/TestJspConfig.java | 145 +++++++++++++++++++++
 .../jasper/servlet/TestJspCServletContext.java     |   2 +-
 .../WEB-INF/tags/error-on-el-not-found-false.tag}  |   7 +-
 .../WEB-INF/tags/error-on-el-not-found-true.tag}   |   7 +-
 test/webapp/WEB-INF/web.xml                        |   8 ++
 .../default.jsp}                                   |   6 +-
 .../page-directive-false.jsp}                      |   7 +-
 .../page-directive-true.jsp}                       |   7 +-
 .../jsp/errorOnELNotFound/tag-file-false.jsp}      |   9 +-
 .../jsp/errorOnELNotFound/tag-file-true.jsp}       |   9 +-
 .../web-xml-false.jsp}                             |   6 +-
 .../web-xml-true.jsp}                              |   6 +-
 webapps/docs/changelog.xml                         |   5 +
 31 files changed, 387 insertions(+), 48 deletions(-)
 copy res/META-INF/jasper-el.jar/services/jakarta.el.ExpressionFactory => java/jakarta/servlet/jsp/LocalStrings.properties (95%)
 copy java/{jakarta/el/VariableMapper.java => org/apache/jasper/runtime/JspSourceDirectives.java} (74%)
 copy test/{webapp-fragments/bug51396.jsp => webapp/WEB-INF/tags/error-on-el-not-found-false.tag} (93%)
 copy test/{webapp-fragments/bug51396.jsp => webapp/WEB-INF/tags/error-on-el-not-found-true.tag} (93%)
 copy test/webapp/jsp/{encoding/bom-none-prolog-none.jsp => errorOnELNotFound/default.jsp} (92%)
 copy test/webapp/jsp/{encoding/bom-none-prolog-none.jsp => errorOnELNotFound/page-directive-false.jsp} (88%)
 copy test/webapp/jsp/{encoding/bom-none-prolog-none.jsp => errorOnELNotFound/page-directive-true.jsp} (89%)
 copy test/{deployment/dirContext/index.html => webapp/jsp/errorOnELNotFound/tag-file-false.jsp} (84%)
 copy test/{deployment/dirContext/index.html => webapp/jsp/errorOnELNotFound/tag-file-true.jsp} (84%)
 copy test/webapp/jsp/{encoding/bom-none-prolog-none.jsp => errorOnELNotFound/web-xml-false.jsp} (92%)
 copy test/webapp/jsp/{encoding/bom-none-prolog-none.jsp => errorOnELNotFound/web-xml-true.jsp} (92%)

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[tomcat] 03/03: Implement the new page/tag directive errorOnELNotFound

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit 37bc60c9efed390f662afe0a1d12d2ba0d91ada8
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Thu Sep 23 21:09:52 2021 +0100

    Implement the new page/tag directive errorOnELNotFound
---
 java/jakarta/servlet/jsp/resources/jspxml.dtd      |  27 ++--
 java/jakarta/servlet/jsp/resources/jspxml.xsd      |   1 +
 java/org/apache/jasper/compiler/Compiler.java      |   4 +
 java/org/apache/jasper/compiler/Generator.java     |  15 +++
 java/org/apache/jasper/compiler/JspConfig.java     |  21 ++-
 java/org/apache/jasper/compiler/PageInfo.java      |  40 ++++++
 .../apache/jasper/compiler/TagFileProcessor.java   |   3 +-
 java/org/apache/jasper/compiler/Validator.java     |  15 +++
 .../jasper/resources/LocalStrings.properties       |   4 +
 .../apache/jasper/runtime/JspContextWrapper.java   |   9 ++
 .../apache/jasper/runtime/JspSourceDirectives.java |  27 ++++
 .../org/apache/jasper/runtime/PageContextImpl.java |   6 +
 .../util/descriptor/web/JspPropertyGroup.java      |   6 +
 .../web/JspPropertyGroupDescriptorImpl.java        |  12 ++
 .../tomcat/util/descriptor/web/WebRuleSet.java     |   2 +
 test/org/apache/jasper/compiler/TestJspConfig.java | 145 +++++++++++++++++++++
 .../jasper/servlet/TestJspCServletContext.java     |   2 +-
 .../WEB-INF/tags/error-on-el-not-found-false.tag   |  18 +++
 .../WEB-INF/tags/error-on-el-not-found-true.tag    |  18 +++
 test/webapp/WEB-INF/web.xml                        |   8 ++
 test/webapp/jsp/errorOnELNotFound/default.jsp      |  21 +++
 .../jsp/errorOnELNotFound/page-directive-false.jsp |  22 ++++
 .../jsp/errorOnELNotFound/page-directive-true.jsp  |  22 ++++
 .../jsp/errorOnELNotFound/tag-file-false.jsp       |  23 ++++
 .../webapp/jsp/errorOnELNotFound/tag-file-true.jsp |  23 ++++
 .../webapp/jsp/errorOnELNotFound/web-xml-false.jsp |  21 +++
 test/webapp/jsp/errorOnELNotFound/web-xml-true.jsp |  21 +++
 webapps/docs/changelog.xml                         |   5 +
 28 files changed, 524 insertions(+), 17 deletions(-)

diff --git a/java/jakarta/servlet/jsp/resources/jspxml.dtd b/java/jakarta/servlet/jsp/resources/jspxml.dtd
index c6f0998..a5fcc5f 100644
--- a/java/jakarta/servlet/jsp/resources/jspxml.dtd
+++ b/java/jakarta/servlet/jsp/resources/jspxml.dtd
@@ -94,19 +94,20 @@
 
 <!ELEMENT jsp:directive.page EMPTY>
 <!ATTLIST jsp:directive.page
-    language        CDATA           "java"
-    extends         %ClassName;     #IMPLIED
-    contentType     %Content;       "text/html; charset=ISO-8859-1"
-    import          CDATA           #IMPLIED
-    session         %Bool;          "true"
-    buffer          CDATA           "8kb"
-    autoFlush       %Bool;          "true"
-    isThreadSafe    %Bool;          "true"
-    info            CDATA           #IMPLIED
-    errorPage       %URL;           #IMPLIED
-    isErrorPage     %Bool;          "false"
-    pageEncoding    CDATA           #IMPLIED
-    isELIgnored     %Bool;          #IMPLIED
+    language            CDATA           "java"
+    extends             %ClassName;     #IMPLIED
+    contentType         %Content;       "text/html; charset=ISO-8859-1"
+    import              CDATA           #IMPLIED
+    session             %Bool;          "true"
+    buffer              CDATA           "8kb"
+    autoFlush           %Bool;          "true"
+    isThreadSafe        %Bool;          "true"
+    info                CDATA           #IMPLIED
+    errorPage           %URL;           #IMPLIED
+    isErrorPage         %Bool;          "false"
+    pageEncoding        CDATA           #IMPLIED
+    isELIgnored         %Bool;          #IMPLIED
+    errorOnELNotFound   %Bool;          "false"
 >
 
 <!-- the jsp:directive.include only appears in JSP documents and does
diff --git a/java/jakarta/servlet/jsp/resources/jspxml.xsd b/java/jakarta/servlet/jsp/resources/jspxml.xsd
index 0e5eba0..4cad6bb 100644
--- a/java/jakarta/servlet/jsp/resources/jspxml.xsd
+++ b/java/jakarta/servlet/jsp/resources/jspxml.xsd
@@ -333,6 +333,7 @@
       <xsd:attribute name = "errorPage" type = "RelativeURL"/>
       <xsd:attribute name = "isErrorPage" default = "false" type = "Bool"/>
       <xsd:attribute name = "isELIgnored" type = "Bool"/>
+      <xsd:attribute name = "errorOnELNotFound" default = "false" type = "Bool"/>
     </xsd:complexType>
   </xsd:element>
 
diff --git a/java/org/apache/jasper/compiler/Compiler.java b/java/org/apache/jasper/compiler/Compiler.java
index 7da6055..b38edae 100644
--- a/java/org/apache/jasper/compiler/Compiler.java
+++ b/java/org/apache/jasper/compiler/Compiler.java
@@ -132,6 +132,10 @@ public abstract class Compiler {
             pageInfo.setELIgnored(JspUtil.booleanValue(jspProperty
                     .isELIgnored()));
         }
+        if (jspProperty.getErrorOnELNotFound() != null) {
+            pageInfo.setErrorOnELNotFound(JspUtil.booleanValue(jspProperty
+                    .getErrorOnELNotFound()));
+        }
         if (jspProperty.isScriptingInvalid() != null) {
             pageInfo.setScriptingInvalid(JspUtil.booleanValue(jspProperty
                     .isScriptingInvalid()));
diff --git a/java/org/apache/jasper/compiler/Generator.java b/java/org/apache/jasper/compiler/Generator.java
index 61eec0c..2872e01 100644
--- a/java/org/apache/jasper/compiler/Generator.java
+++ b/java/org/apache/jasper/compiler/Generator.java
@@ -700,6 +700,17 @@ class Generator {
         out.printil("}");
         out.println();
 
+        // Implement JspSourceDirectives
+        out.printil("public boolean getErrorOnELNotFound() {");
+        out.pushIndent();
+        if (pageInfo.isErrorOnELNotFound()) {
+            out.printil("return true;");
+        } else {
+            out.printil("return false;");
+        }
+        out.popIndent();
+        out.printil("}");
+        out.println();
 
         generateGetters();
         generateInit();
@@ -733,6 +744,8 @@ class Generator {
             out.println(",");
             out.printin("                 jakarta.servlet.SingleThreadModel");
         }
+        out.println(",");
+        out.printin("                 org.apache.jasper.runtime.JspSourceDirectives");
         out.println(" {");
         out.pushIndent();
 
@@ -3652,6 +3665,8 @@ class Generator {
             out.println(",");
             out.printin("               jakarta.servlet.jsp.tagext.DynamicAttributes");
         }
+        out.println(",");
+        out.printin("                 org.apache.jasper.runtime.JspSourceDirectives");
         out.println(" {");
         out.pushIndent();
 
diff --git a/java/org/apache/jasper/compiler/JspConfig.java b/java/org/apache/jasper/compiler/JspConfig.java
index f63109a..7cb3b64 100644
--- a/java/org/apache/jasper/compiler/JspConfig.java
+++ b/java/org/apache/jasper/compiler/JspConfig.java
@@ -46,6 +46,7 @@ public class JspConfig {
 
     private static final String defaultIsXml = null;    // unspecified
     private String defaultIsELIgnored = null;           // unspecified
+    private String defaultErrorOnELNotFound = "false";
     private static final String defaultIsScriptingInvalid = null;
     private String defaultDeferedSyntaxAllowedAsLiteral = null;
     private static final String defaultTrimDirectiveWhitespaces = null;
@@ -96,6 +97,7 @@ public class JspConfig {
 
             JspProperty property = new JspProperty(jspPropertyGroup.getIsXml(),
                     jspPropertyGroup.getElIgnored(),
+                    jspPropertyGroup.getErrorOnELNotFound(),
                     jspPropertyGroup.getScriptingInvalid(),
                     jspPropertyGroup.getPageEncoding(),
                     jspPropertyGroup.getIncludePreludes(),
@@ -164,6 +166,7 @@ public class JspConfig {
                     processWebDotXml();
                     defaultJspProperty = new JspProperty(defaultIsXml,
                             defaultIsELIgnored,
+                            defaultErrorOnELNotFound,
                             defaultIsScriptingInvalid,
                             null, null, null,
                             defaultDeferedSyntaxAllowedAsLiteral,
@@ -245,6 +248,7 @@ public class JspConfig {
 
         JspPropertyGroup isXmlMatch = null;
         JspPropertyGroup elIgnoredMatch = null;
+        JspPropertyGroup errorOnELNotFoundMatch = null;
         JspPropertyGroup scriptingInvalidMatch = null;
         JspPropertyGroup pageEncodingMatch = null;
         JspPropertyGroup deferedSyntaxAllowedAsLiteralMatch = null;
@@ -296,6 +300,9 @@ public class JspConfig {
             if (jp.isELIgnored() != null) {
                 elIgnoredMatch = selectProperty(elIgnoredMatch, jpg);
             }
+            if (jp.getErrorOnELNotFound() != null) {
+                errorOnELNotFoundMatch = selectProperty(errorOnELNotFoundMatch, jpg);
+            }
             if (jp.isScriptingInvalid() != null) {
                 scriptingInvalidMatch =
                     selectProperty(scriptingInvalidMatch, jpg);
@@ -327,6 +334,7 @@ public class JspConfig {
 
         String isXml = defaultIsXml;
         String isELIgnored = defaultIsELIgnored;
+        String errorOnELNotFound = defaultErrorOnELNotFound;
         String isScriptingInvalid = defaultIsScriptingInvalid;
         String pageEncoding = null;
         String isDeferedSyntaxAllowedAsLiteral = defaultDeferedSyntaxAllowedAsLiteral;
@@ -338,6 +346,9 @@ public class JspConfig {
         if (isXmlMatch != null) {
             isXml = isXmlMatch.getJspProperty().isXml();
         }
+        if (errorOnELNotFoundMatch != null) {
+            errorOnELNotFound = errorOnELNotFoundMatch.getJspProperty().getErrorOnELNotFound();
+        }
         if (elIgnoredMatch != null) {
             isELIgnored = elIgnoredMatch.getJspProperty().isELIgnored();
         }
@@ -368,7 +379,7 @@ public class JspConfig {
                 errorOnUndeclaredNamespaceMatch.getJspProperty().isErrorOnUndeclaredNamespace();
         }
 
-        return new JspProperty(isXml, isELIgnored, isScriptingInvalid,
+        return new JspProperty(isXml, isELIgnored, errorOnELNotFound, isScriptingInvalid,
                 pageEncoding, includePreludes, includeCodas,
                 isDeferedSyntaxAllowedAsLiteral, isTrimDirectiveWhitespaces,
                 defaultContentType, buffer, errorOnUndeclaredNamespace);
@@ -448,6 +459,7 @@ public class JspConfig {
 
         private final String isXml;
         private final String elIgnored;
+        private final String errorOnELNotFound;
         private final String scriptingInvalid;
         private final String pageEncoding;
         private final Collection<String> includePrelude;
@@ -458,7 +470,7 @@ public class JspConfig {
         private final String buffer;
         private final String errorOnUndeclaredNamespace;
 
-        public JspProperty(String isXml, String elIgnored,
+        public JspProperty(String isXml, String elIgnored, String errorOnELNotFound,
                 String scriptingInvalid, String pageEncoding,
                 Collection<String> includePrelude, Collection<String> includeCoda,
                 String deferedSyntaxAllowedAsLiteral,
@@ -469,6 +481,7 @@ public class JspConfig {
 
             this.isXml = isXml;
             this.elIgnored = elIgnored;
+            this.errorOnELNotFound = errorOnELNotFound;
             this.scriptingInvalid = scriptingInvalid;
             this.pageEncoding = pageEncoding;
             this.includePrelude = includePrelude;
@@ -488,6 +501,10 @@ public class JspConfig {
             return elIgnored;
         }
 
+        public String getErrorOnELNotFound() {
+            return errorOnELNotFound;
+        }
+
         public String isScriptingInvalid() {
             return scriptingInvalid;
         }
diff --git a/java/org/apache/jasper/compiler/PageInfo.java b/java/org/apache/jasper/compiler/PageInfo.java
index 464a5c9..5c0a2c0 100644
--- a/java/org/apache/jasper/compiler/PageInfo.java
+++ b/java/org/apache/jasper/compiler/PageInfo.java
@@ -100,6 +100,10 @@ class PageInfo {
     // JSP 2.2
     private boolean errorOnUndeclaredNamespace = false;
 
+    // JSP 3.1
+    private String errorOnELNotFoundValue;
+    private boolean errorOnELNotFound = false;
+
     private final boolean isTagFile;
 
     PageInfo(BeanRepository beanRepository, JspCompilationContext ctxt) {
@@ -635,6 +639,30 @@ class PageInfo {
         isELIgnoredValue = value;
     }
 
+
+    /*
+     * errorOnELNotFound
+     */
+    public void setErrorOnELNotFound(String value, Node n, ErrorDispatcher err,
+                   boolean pagedir)
+        throws JasperException {
+
+        if ("true".equalsIgnoreCase(value)) {
+            errorOnELNotFound = true;
+        } else if ("false".equalsIgnoreCase(value)) {
+            errorOnELNotFound = false;
+        } else {
+            if (pagedir) {
+                err.jspError(n, "jsp.error.page.invalid.errorOnELNotFound");
+            } else {
+                err.jspError(n, "jsp.error.tag.invalid.errorOnELNotFound");
+            }
+        }
+
+        errorOnELNotFoundValue = value;
+    }
+
+
     /*
      * deferredSyntaxAllowedAsLiteral
      */
@@ -691,6 +719,18 @@ class PageInfo {
         return isELIgnored;
     }
 
+    public void setErrorOnELNotFound(boolean s) {
+        errorOnELNotFound = s;
+    }
+
+    public String getErrorOnELNotFound() {
+        return errorOnELNotFoundValue;
+    }
+
+    public boolean isErrorOnELNotFound() {
+        return errorOnELNotFound;
+    }
+
     public void putNonCustomTagPrefix(String prefix, Mark where) {
         nonCustomTagPrefixMap.put(prefix, where);
     }
diff --git a/java/org/apache/jasper/compiler/TagFileProcessor.java b/java/org/apache/jasper/compiler/TagFileProcessor.java
index e6a1773..e1ed7c1 100644
--- a/java/org/apache/jasper/compiler/TagFileProcessor.java
+++ b/java/org/apache/jasper/compiler/TagFileProcessor.java
@@ -68,7 +68,8 @@ class TagFileProcessor {
                 new JspUtil.ValidAttribute("import"),
                 new JspUtil.ValidAttribute("deferredSyntaxAllowedAsLiteral"), // JSP 2.1
                 new JspUtil.ValidAttribute("trimDirectiveWhitespaces"), // JSP 2.1
-                new JspUtil.ValidAttribute("isELIgnored") };
+                new JspUtil.ValidAttribute("isELIgnored"),
+                new JspUtil.ValidAttribute("errorOnELNotFound") };
 
         private static final JspUtil.ValidAttribute[] attributeDirectiveAttrs = {
                 new JspUtil.ValidAttribute("name", true),
diff --git a/java/org/apache/jasper/compiler/Validator.java b/java/org/apache/jasper/compiler/Validator.java
index 61bc587..94d0b2c 100644
--- a/java/org/apache/jasper/compiler/Validator.java
+++ b/java/org/apache/jasper/compiler/Validator.java
@@ -82,6 +82,7 @@ class Validator {
             new JspUtil.ValidAttribute("contentType"),
             new JspUtil.ValidAttribute("pageEncoding"),
             new JspUtil.ValidAttribute("isELIgnored"),
+            new JspUtil.ValidAttribute("errorOnELNotFound"),
             new JspUtil.ValidAttribute("deferredSyntaxAllowedAsLiteral"),
             new JspUtil.ValidAttribute("trimDirectiveWhitespaces")
         };
@@ -174,6 +175,13 @@ class Validator {
                         err.jspError(n, "jsp.error.page.conflict.iselignored",
                                 pageInfo.getIsELIgnored(), value);
                     }
+                } else if ("errorOnELNotFound".equals(attr)) {
+                    if (pageInfo.getErrorOnELNotFound() == null) {
+                        pageInfo.setErrorOnELNotFound(value, n, err, true);
+                    } else if (!pageInfo.getErrorOnELNotFound().equals(value)) {
+                        err.jspError(n, "jsp.error.page.conflict.errorOnELNotFound",
+                                pageInfo.getErrorOnELNotFound(), value);
+                    }
                 } else if ("isErrorPage".equals(attr)) {
                     if (pageInfo.getIsErrorPage() == null) {
                         pageInfo.setIsErrorPage(value, n, err);
@@ -270,6 +278,13 @@ class Validator {
                         err.jspError(n, "jsp.error.tag.conflict.iselignored",
                                 pageInfo.getIsELIgnored(), value);
                     }
+                } else if ("errorOnELNotFound".equals(attr)) {
+                    if (pageInfo.getErrorOnELNotFound() == null) {
+                        pageInfo.setErrorOnELNotFound(value, n, err, false);
+                    } else if (!pageInfo.getErrorOnELNotFound().equals(value)) {
+                        err.jspError(n, "jsp.error.tag.conflict.errorOnELNotFound",
+                                pageInfo.getErrorOnELNotFound(), value);
+                    }
                 } else if ("pageEncoding".equals(attr)) {
                     if (pageEncodingSeen) {
                         err.jspError(n, "jsp.error.tag.multi.pageencoding");
diff --git a/java/org/apache/jasper/resources/LocalStrings.properties b/java/org/apache/jasper/resources/LocalStrings.properties
index 898e173..3a0f990 100644
--- a/java/org/apache/jasper/resources/LocalStrings.properties
+++ b/java/org/apache/jasper/resources/LocalStrings.properties
@@ -143,6 +143,7 @@ jsp.error.page.conflict.autoflush=Page directive: illegal to have multiple occur
 jsp.error.page.conflict.buffer=Page directive: illegal to have multiple occurrences of ''buffer'' with different values (old: [{0}], new: [{1}])
 jsp.error.page.conflict.contenttype=Page directive: illegal to have multiple occurrences of ''contentType'' with different values (old: [{0}], new: [{1}])
 jsp.error.page.conflict.deferredsyntaxallowedasliteral=Page directive: illegal to have multiple occurrences of ''deferredSyntaxAllowedAsLiteral'' with different values (old: [{0}], new: [{1}])
+jsp.error.page.conflict.errorOnELNotFound=Page directive: illegal to have multiple occurrences of ''errorOnELNotFound'' with different values (old: [{0}], new: [{1}])
 jsp.error.page.conflict.errorpage=Page directive: illegal to have multiple occurrences of ''errorPage'' with different values (old: [{0}], new: [{1}])
 jsp.error.page.conflict.extends=Page directive: illegal to have multiple occurrences of ''extends'' with different values (old: [{0}], new: [{1}])
 jsp.error.page.conflict.info=Page directive: illegal to have multiple occurrences of ''info'' with different values (old: [{0}], new: [{1}])
@@ -154,6 +155,7 @@ jsp.error.page.conflict.session=Page directive: illegal to have multiple occurre
 jsp.error.page.conflict.trimdirectivewhitespaces=Page directive: illegal to have multiple occurrences of ''trimDirectiveWhitespaces'' with different values (old: [{0}], new: [{1}])
 jsp.error.page.invalid.buffer=Page directive: invalid value for buffer
 jsp.error.page.invalid.deferredsyntaxallowedasliteral=Page directive: invalid value for deferredSyntaxAllowedAsLiteral
+jsp.error.page.invalid.errorOnELNotFound=Page directive: invalid value for errorOnELNotFound
 jsp.error.page.invalid.import=Page directive: invalid value for import
 jsp.error.page.invalid.iselignored=Page directive: invalid value for isELIgnored
 jsp.error.page.invalid.iserrorpage=Page directive: invalid value for isErrorPage
@@ -200,10 +202,12 @@ jsp.error.stream.closed=Stream closed
 jsp.error.string_interpreter_class.instantiation=Failed to load or instantiate StringInterpreter class [{0}]
 jsp.error.tag.conflict.attr=Tag directive: illegal to have multiple occurrences of the attribute [{0}] with different values (old: [{1}], new: [{2}])
 jsp.error.tag.conflict.deferredsyntaxallowedasliteral=Tag directive: illegal to have multiple occurrences of ''deferredSyntaxAllowedAsLiteral'' with different values (old: [{0}], new: [{1}])
+jsp.error.tag.conflict.errorOnELNotFound=Tag directive: illegal to have multiple occurrences of ''errorOnELNotFound'' with different values (old: [{0}], new: [{1}])
 jsp.error.tag.conflict.iselignored=Tag directive: illegal to have multiple occurrences of ''isELIgnored'' with different values (old: [{0}], new: [{1}])
 jsp.error.tag.conflict.language=Tag directive: illegal to have multiple occurrences of ''language'' with different values (old: [{0}], new: [{1}])
 jsp.error.tag.conflict.trimdirectivewhitespaces=Tag directive: illegal to have multiple occurrences of ''trimDirectiveWhitespaces'' with different values (old: [{0}], new: [{1}])
 jsp.error.tag.invalid.deferredsyntaxallowedasliteral=Tag directive: invalid value for deferredSyntaxAllowedAsLiteral
+jsp.error.tag.invalid.errorOnELNotFound=Tag directive: invalid value for errorOnELNotFound
 jsp.error.tag.invalid.iselignored=Tag directive: invalid value for isELIgnored
 jsp.error.tag.invalid.trimdirectivewhitespaces=Tag directive: invalid value for trimDirectiveWhitespaces
 jsp.error.tag.language.nonjava=Tag directive: invalid language attribute
diff --git a/java/org/apache/jasper/runtime/JspContextWrapper.java b/java/org/apache/jasper/runtime/JspContextWrapper.java
index 718c803..a7820a7 100644
--- a/java/org/apache/jasper/runtime/JspContextWrapper.java
+++ b/java/org/apache/jasper/runtime/JspContextWrapper.java
@@ -48,6 +48,7 @@ import jakarta.servlet.jsp.JspWriter;
 import jakarta.servlet.jsp.PageContext;
 import jakarta.servlet.jsp.el.ELException;
 import jakarta.servlet.jsp.el.ExpressionEvaluator;
+import jakarta.servlet.jsp.el.NotFoundELResolver;
 import jakarta.servlet.jsp.el.VariableResolver;
 import jakarta.servlet.jsp.tagext.BodyContent;
 import jakarta.servlet.jsp.tagext.JspTag;
@@ -563,6 +564,14 @@ public class JspContextWrapper extends PageContext implements VariableResolver {
             if (key == JspContext.class) {
                 return pageContext;
             }
+            if (key == NotFoundELResolver.class) {
+                if (jspTag instanceof JspSourceDirectives) {
+                    return Boolean.valueOf(((JspSourceDirectives) jspTag).getErrorOnELNotFound());
+                } else {
+                    // returning Boolean.FALSE would have the same effect
+                    return null;
+                }
+            }
             return wrapped.getContext(key);
         }
 
diff --git a/java/org/apache/jasper/runtime/JspSourceDirectives.java b/java/org/apache/jasper/runtime/JspSourceDirectives.java
new file mode 100644
index 0000000..cb531ac
--- /dev/null
+++ b/java/org/apache/jasper/runtime/JspSourceDirectives.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jasper.runtime;
+
+/**
+ * Provides runtime access to selected compile time directives. Page directives
+ * are not added to this interface until there is a requirement to access them
+ *  at runtime.
+ */
+public interface JspSourceDirectives {
+
+    boolean getErrorOnELNotFound();
+}
diff --git a/java/org/apache/jasper/runtime/PageContextImpl.java b/java/org/apache/jasper/runtime/PageContextImpl.java
index 1477013..3000439 100644
--- a/java/org/apache/jasper/runtime/PageContextImpl.java
+++ b/java/org/apache/jasper/runtime/PageContextImpl.java
@@ -43,6 +43,7 @@ import jakarta.servlet.jsp.JspException;
 import jakarta.servlet.jsp.JspFactory;
 import jakarta.servlet.jsp.JspWriter;
 import jakarta.servlet.jsp.PageContext;
+import jakarta.servlet.jsp.el.NotFoundELResolver;
 import jakarta.servlet.jsp.tagext.BodyContent;
 
 import org.apache.jasper.Constants;
@@ -721,6 +722,11 @@ public class PageContextImpl extends PageContext {
                     }
                 }
             }
+            if (servlet instanceof JspSourceDirectives) {
+                if (((JspSourceDirectives) servlet).getErrorOnELNotFound()) {
+                    elContext.putContext(NotFoundELResolver.class, Boolean.TRUE);
+                }
+            }
         }
         return this.elContext;
     }
diff --git a/java/org/apache/tomcat/util/descriptor/web/JspPropertyGroup.java b/java/org/apache/tomcat/util/descriptor/web/JspPropertyGroup.java
index 9246c60..07f3dd3 100644
--- a/java/org/apache/tomcat/util/descriptor/web/JspPropertyGroup.java
+++ b/java/org/apache/tomcat/util/descriptor/web/JspPropertyGroup.java
@@ -34,6 +34,12 @@ public class JspPropertyGroup extends XmlEncodingBase {
     }
     public Boolean getDeferredSyntax() { return deferredSyntax; }
 
+    private Boolean errorOnELNotFound = null;
+    public void setErrorOnELNotFound(String errorOnELNotFound) {
+        this.errorOnELNotFound = Boolean.valueOf(errorOnELNotFound);
+    }
+    public Boolean getErrorOnELNotFound() { return errorOnELNotFound; }
+
     private Boolean elIgnored = null;
     public void setElIgnored(String elIgnored) {
         this.elIgnored = Boolean.valueOf(elIgnored);
diff --git a/java/org/apache/tomcat/util/descriptor/web/JspPropertyGroupDescriptorImpl.java b/java/org/apache/tomcat/util/descriptor/web/JspPropertyGroupDescriptorImpl.java
index 4785ee2..0f67f61 100644
--- a/java/org/apache/tomcat/util/descriptor/web/JspPropertyGroupDescriptorImpl.java
+++ b/java/org/apache/tomcat/util/descriptor/web/JspPropertyGroupDescriptorImpl.java
@@ -72,6 +72,18 @@ public class JspPropertyGroupDescriptorImpl
 
 
     @Override
+    public String getErrorOnELNotFound() {
+        String result = null;
+
+        if (jspPropertyGroup.getErrorOnELNotFound() != null) {
+            result = jspPropertyGroup.getErrorOnELNotFound().toString();
+        }
+
+        return result;
+    }
+
+
+    @Override
     public String getErrorOnUndeclaredNamespace() {
         String result = null;
 
diff --git a/java/org/apache/tomcat/util/descriptor/web/WebRuleSet.java b/java/org/apache/tomcat/util/descriptor/web/WebRuleSet.java
index 2472aae..ba3bd53 100644
--- a/java/org/apache/tomcat/util/descriptor/web/WebRuleSet.java
+++ b/java/org/apache/tomcat/util/descriptor/web/WebRuleSet.java
@@ -283,6 +283,8 @@ public class WebRuleSet implements RuleSet {
                                "setDeferredSyntax", 0);
         digester.addCallMethod(fullPrefix + "/jsp-config/jsp-property-group/el-ignored",
                                "setElIgnored", 0);
+        digester.addCallMethod(fullPrefix + "/jsp-config/jsp-property-group/error-on-el-not-found",
+                               "setErrorOnELNotFound", 0);
         digester.addCallMethod(fullPrefix + "/jsp-config/jsp-property-group/include-coda",
                                "addIncludeCoda", 0);
         digester.addCallMethod(fullPrefix + "/jsp-config/jsp-property-group/include-prelude",
diff --git a/test/org/apache/jasper/compiler/TestJspConfig.java b/test/org/apache/jasper/compiler/TestJspConfig.java
index 9389c2c..64f6d0c 100644
--- a/test/org/apache/jasper/compiler/TestJspConfig.java
+++ b/test/org/apache/jasper/compiler/TestJspConfig.java
@@ -18,6 +18,8 @@ package org.apache.jasper.compiler;
 
 import java.io.File;
 
+import jakarta.servlet.http.HttpServletResponse;
+
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -192,4 +194,147 @@ public class TestJspConfig extends TomcatBaseTest {
 
         Assert.assertTrue(result.indexOf("<p>00-hello world</p>") > 0);
     }
+
+    @Test
+    public void testErrorOnELNotFound01() throws Exception {
+        // Defaults
+
+        Tomcat tomcat = getTomcatInstance();
+
+        File appDir = new File("test/webapp");
+        tomcat.addWebapp(null, "/test", appDir.getAbsolutePath());
+
+        tomcat.start();
+
+        ByteChunk res = new ByteChunk();
+        int rc = getUrl("http://localhost:" + getPort() + "/test/jsp/errorOnELNotFound/default.jsp", res, null);
+
+        Assert.assertEquals(HttpServletResponse.SC_OK, rc);
+
+        String result = res.toString();
+        Assert.assertTrue(result, result.indexOf("<p>00-OK</p>") > 0);
+    }
+
+    @Test
+    public void testErrorOnELNotFound02() throws Exception {
+        // Page directive true
+
+        Tomcat tomcat = getTomcatInstance();
+
+        File appDir = new File("test/webapp");
+        tomcat.addWebapp(null, "/test", appDir.getAbsolutePath());
+
+        tomcat.start();
+
+        ByteChunk res = new ByteChunk();
+        int rc = getUrl("http://localhost:" + getPort() + "/test/jsp/errorOnELNotFound/page-directive-true.jsp", res, null);
+
+        Assert.assertEquals(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, rc);
+
+        // Look for the non-i18n part of the Exception message
+        String result = res.toString();
+        Assert.assertTrue(result, result.indexOf("[unknown]") > 0);
+    }
+
+    @Test
+    public void testErrorOnELNotFound03() throws Exception {
+        // Page directive false
+
+        Tomcat tomcat = getTomcatInstance();
+
+        File appDir = new File("test/webapp");
+        tomcat.addWebapp(null, "/test", appDir.getAbsolutePath());
+
+        tomcat.start();
+
+        ByteChunk res = new ByteChunk();
+        int rc = getUrl("http://localhost:" + getPort() + "/test/jsp/errorOnELNotFound/page-directive-false.jsp", res, null);
+
+        Assert.assertEquals(HttpServletResponse.SC_OK, rc);
+
+        String result = res.toString();
+        Assert.assertTrue(result, result.indexOf("<p>00-OK</p>") > 0);
+    }
+
+    @Test
+    public void testErrorOnELNotFound04() throws Exception {
+        // web.xml true
+
+        Tomcat tomcat = getTomcatInstance();
+
+        File appDir = new File("test/webapp");
+        tomcat.addWebapp(null, "/test", appDir.getAbsolutePath());
+
+        tomcat.start();
+
+        ByteChunk res = new ByteChunk();
+        int rc = getUrl("http://localhost:" + getPort() + "/test/jsp/errorOnELNotFound/web-xml-true.jsp", res, null);
+
+        Assert.assertEquals(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, rc);
+
+        // Look for the non-i18n part of the Exception message
+        String result = res.toString();
+        Assert.assertTrue(result, result.indexOf("[unknown]") > 0);
+    }
+
+    @Test
+    public void testErrorOnELNotFound05() throws Exception {
+        // web.xml false
+
+        Tomcat tomcat = getTomcatInstance();
+
+        File appDir = new File("test/webapp");
+        tomcat.addWebapp(null, "/test", appDir.getAbsolutePath());
+
+        tomcat.start();
+
+        ByteChunk res = new ByteChunk();
+        int rc = getUrl("http://localhost:" + getPort() + "/test/jsp/errorOnELNotFound/web-xml-false.jsp", res, null);
+
+        Assert.assertEquals(HttpServletResponse.SC_OK, rc);
+
+        String result = res.toString();
+        Assert.assertTrue(result, result.indexOf("<p>00-OK</p>") > 0);
+    }
+
+    @Test
+    public void testErrorOnELNotFound06() throws Exception {
+        // tag file true
+
+        Tomcat tomcat = getTomcatInstance();
+
+        File appDir = new File("test/webapp");
+        tomcat.addWebapp(null, "/test", appDir.getAbsolutePath());
+
+        tomcat.start();
+
+        ByteChunk res = new ByteChunk();
+        int rc = getUrl("http://localhost:" + getPort() + "/test/jsp/errorOnELNotFound/tag-file-true.jsp", res, null);
+
+        Assert.assertEquals(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, rc);
+
+        // Look for the non-i18n part of the Exception message
+        String result = res.toString();
+        Assert.assertTrue(result, result.indexOf("[unknown]") > 0);
+    }
+
+    @Test
+    public void testErrorOnELNotFound07() throws Exception {
+        // tag file false
+
+        Tomcat tomcat = getTomcatInstance();
+
+        File appDir = new File("test/webapp");
+        tomcat.addWebapp(null, "/test", appDir.getAbsolutePath());
+
+        tomcat.start();
+
+        ByteChunk res = new ByteChunk();
+        int rc = getUrl("http://localhost:" + getPort() + "/test/jsp/errorOnELNotFound/tag-file-false.jsp", res, null);
+
+        Assert.assertEquals(HttpServletResponse.SC_OK, rc);
+
+        String result = res.toString();
+        Assert.assertTrue(result, result.indexOf("<p>00-OK</p>") > 0);
+    }
 }
diff --git a/test/org/apache/jasper/servlet/TestJspCServletContext.java b/test/org/apache/jasper/servlet/TestJspCServletContext.java
index f8d0adb..cc0032e 100644
--- a/test/org/apache/jasper/servlet/TestJspCServletContext.java
+++ b/test/org/apache/jasper/servlet/TestJspCServletContext.java
@@ -41,7 +41,7 @@ public class TestJspCServletContext {
         Assert.assertTrue(jspConfigDescriptor.getTaglibs().isEmpty());
         Collection<JspPropertyGroupDescriptor> propertyGroups =
                 jspConfigDescriptor.getJspPropertyGroups();
-        Assert.assertEquals(4, propertyGroups.size());
+        Assert.assertEquals(6, propertyGroups.size());
         Iterator<JspPropertyGroupDescriptor> groupIterator =
                 propertyGroups.iterator();
         JspPropertyGroupDescriptor groupDescriptor;
diff --git a/test/webapp/WEB-INF/tags/error-on-el-not-found-false.tag b/test/webapp/WEB-INF/tags/error-on-el-not-found-false.tag
new file mode 100644
index 0000000..8466d0e
--- /dev/null
+++ b/test/webapp/WEB-INF/tags/error-on-el-not-found-false.tag
@@ -0,0 +1,18 @@
+<%--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+--%>
+<%@ tag errorOnELNotFound="false" %>
+<p>00-O${unknown}K</p>
\ No newline at end of file
diff --git a/test/webapp/WEB-INF/tags/error-on-el-not-found-true.tag b/test/webapp/WEB-INF/tags/error-on-el-not-found-true.tag
new file mode 100644
index 0000000..ba23cac
--- /dev/null
+++ b/test/webapp/WEB-INF/tags/error-on-el-not-found-true.tag
@@ -0,0 +1,18 @@
+<%--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+--%>
+<%@ tag errorOnELNotFound="true" %>
+<p>00-O${unknown}K</p>
\ No newline at end of file
diff --git a/test/webapp/WEB-INF/web.xml b/test/webapp/WEB-INF/web.xml
index 0a28fc1..b1f30f0 100644
--- a/test/webapp/WEB-INF/web.xml
+++ b/test/webapp/WEB-INF/web.xml
@@ -152,6 +152,14 @@
       <page-encoding>ISO-8859-1</page-encoding>
       <is-xml>true</is-xml>
     </jsp-property-group>
+    <jsp-property-group>
+      <url-pattern>/jsp/errorOnELNotFound/web-xml-true.jsp</url-pattern>
+      <error-on-el-not-found>true</error-on-el-not-found>
+    </jsp-property-group>
+    <jsp-property-group>
+      <url-pattern>/jsp/errorOnELNotFound/web-xml-false.jsp</url-pattern>
+      <error-on-el-not-found>false</error-on-el-not-found>
+    </jsp-property-group>
   </jsp-config>
 
   <servlet>
diff --git a/test/webapp/jsp/errorOnELNotFound/default.jsp b/test/webapp/jsp/errorOnELNotFound/default.jsp
new file mode 100644
index 0000000..a3e66c9
--- /dev/null
+++ b/test/webapp/jsp/errorOnELNotFound/default.jsp
@@ -0,0 +1,21 @@
+<%--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+--%>
+<html>
+  <body>
+    <p>00-O${unknown}K</p>
+  </body>
+</html>
\ No newline at end of file
diff --git a/test/webapp/jsp/errorOnELNotFound/page-directive-false.jsp b/test/webapp/jsp/errorOnELNotFound/page-directive-false.jsp
new file mode 100644
index 0000000..26ba5de
--- /dev/null
+++ b/test/webapp/jsp/errorOnELNotFound/page-directive-false.jsp
@@ -0,0 +1,22 @@
+<%--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+--%>
+<%@ page errorOnELNotFound="false" %>
+<html>
+  <body>
+    <p>00-O${unknown}K</p>
+  </body>
+</html>
\ No newline at end of file
diff --git a/test/webapp/jsp/errorOnELNotFound/page-directive-true.jsp b/test/webapp/jsp/errorOnELNotFound/page-directive-true.jsp
new file mode 100644
index 0000000..fe241b0
--- /dev/null
+++ b/test/webapp/jsp/errorOnELNotFound/page-directive-true.jsp
@@ -0,0 +1,22 @@
+<%--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+--%>
+<%@ page errorOnELNotFound="true" %>
+<html>
+  <body>
+    <p>00-O${unknown}K</p>
+  </body>
+</html>
\ No newline at end of file
diff --git a/test/webapp/jsp/errorOnELNotFound/tag-file-false.jsp b/test/webapp/jsp/errorOnELNotFound/tag-file-false.jsp
new file mode 100644
index 0000000..df20a0b
--- /dev/null
+++ b/test/webapp/jsp/errorOnELNotFound/tag-file-false.jsp
@@ -0,0 +1,23 @@
+<%--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+--%>
+<%@ page errorOnELNotFound="true" %>
+<%@ taglib prefix="tags" tagdir="/WEB-INF/tags" %>
+<html>
+  <body>
+    <tags:error-on-el-not-found-false />
+  </body>
+</html>
\ No newline at end of file
diff --git a/test/webapp/jsp/errorOnELNotFound/tag-file-true.jsp b/test/webapp/jsp/errorOnELNotFound/tag-file-true.jsp
new file mode 100644
index 0000000..84c9021
--- /dev/null
+++ b/test/webapp/jsp/errorOnELNotFound/tag-file-true.jsp
@@ -0,0 +1,23 @@
+<%--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+--%>
+<%@ page errorOnELNotFound="false" %>
+<%@ taglib prefix="tags" tagdir="/WEB-INF/tags" %>
+<html>
+  <body>
+    <tags:error-on-el-not-found-true />
+  </body>
+</html>
\ No newline at end of file
diff --git a/test/webapp/jsp/errorOnELNotFound/web-xml-false.jsp b/test/webapp/jsp/errorOnELNotFound/web-xml-false.jsp
new file mode 100644
index 0000000..a3e66c9
--- /dev/null
+++ b/test/webapp/jsp/errorOnELNotFound/web-xml-false.jsp
@@ -0,0 +1,21 @@
+<%--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+--%>
+<html>
+  <body>
+    <p>00-O${unknown}K</p>
+  </body>
+</html>
\ No newline at end of file
diff --git a/test/webapp/jsp/errorOnELNotFound/web-xml-true.jsp b/test/webapp/jsp/errorOnELNotFound/web-xml-true.jsp
new file mode 100644
index 0000000..a3e66c9
--- /dev/null
+++ b/test/webapp/jsp/errorOnELNotFound/web-xml-true.jsp
@@ -0,0 +1,21 @@
+<%--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+--%>
+<html>
+  <body>
+    <p>00-O${unknown}K</p>
+  </body>
+</html>
\ No newline at end of file
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 5aba0a1..efe4093 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -179,6 +179,11 @@
         rather than the types being passed explicitly to
         <code>ExpressionFactory.createMethodExpression()</code>. (markt)
       </fix>
+      <add>
+        Add support for a new page/tag directive <code>errorOnELNotFound</code>
+        that can be used to trigger an identifier if an EL expression in a
+        page/tag contains an identifier that cannot be resolved. (markt)
+      </add>
     </changelog>
   </subsection>
   <subsection name="Web applications">

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[tomcat] 02/03: JSP API updates required to implement errorOnELNotFound

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit f6d14bbc764c293c409cc4b03eb0737cd594cacb
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Thu Sep 23 21:07:19 2021 +0100

    JSP API updates required to implement errorOnELNotFound
---
 java/jakarta/servlet/jsp/LocalStrings.properties   | 16 +++++++++++++++
 .../jakarta/servlet/jsp/el/NotFoundELResolver.java | 24 +++++++++++++++++++++-
 2 files changed, 39 insertions(+), 1 deletion(-)

diff --git a/java/jakarta/servlet/jsp/LocalStrings.properties b/java/jakarta/servlet/jsp/LocalStrings.properties
new file mode 100644
index 0000000..2b34d2c
--- /dev/null
+++ b/java/jakarta/servlet/jsp/LocalStrings.properties
@@ -0,0 +1,16 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+el.unknown.identifier=Unknown identifier
\ No newline at end of file
diff --git a/java/jakarta/servlet/jsp/el/NotFoundELResolver.java b/java/jakarta/servlet/jsp/el/NotFoundELResolver.java
index 90fd930..517758f 100644
--- a/java/jakarta/servlet/jsp/el/NotFoundELResolver.java
+++ b/java/jakarta/servlet/jsp/el/NotFoundELResolver.java
@@ -20,9 +20,11 @@ import java.beans.FeatureDescriptor;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.Objects;
+import java.util.ResourceBundle;
 
 import jakarta.el.ELContext;
 import jakarta.el.ELResolver;
+import jakarta.el.PropertyNotFoundException;
 
 /**
  * The final resolver of the Jakarta Server Pages ELResolver chain. It always
@@ -32,16 +34,36 @@ import jakarta.el.ELResolver;
  */
 public class NotFoundELResolver extends ELResolver {
 
+    private static final String LSTRING_FILE = "jakarta.servlet.jsp.LocalStrings";
+    private static final ResourceBundle lStrings = ResourceBundle.getBundle(LSTRING_FILE);
+
     /**
      * {@inheritDoc}
      * <p>
-     * Always resolves the property and always returns {@code null}.
+     * Resolves the property and always returns {@code null} unless the provided
+     * context contains a Boolean object with value {@code Boolean.TRUE} as the
+     * value associated with the key
+     * {@code jakarta.servlet.jsp.el.NotFoundELResolver.class} in which case an
+     * exception is thrown. This is to support implementation of the
+     * {@code errorOnELNotFound} page/tag directive.
      *
      * @return Always {@code null}
+     *
+     * @throws PropertyNotFoundException if the provided context contains a
+     *         Boolean object with value {@code Boolean.TRUE} as the value
+     *         associated with the key
+     *         {@code jakarta.servlet.jsp.el.NotFoundELResolver.class}
      */
     @Override
     public Object getValue(ELContext context, Object base, Object property) {
         Objects.requireNonNull(context);
+
+        Object obj = context.getContext(this.getClass());
+        if (obj instanceof Boolean && ((Boolean) obj).booleanValue()) {
+            throw new PropertyNotFoundException(
+                    lStrings.getString("el.unknown.identifier") + " [" + property.toString() + "]");
+        }
+
         context.setPropertyResolved(base, property);
         return null;
     }

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[tomcat] 01/03: Servlet API changes required to support errorOnELNotFound

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit 0d421d66bb229466c3d10b2679fb9784626a8399
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Thu Sep 23 20:09:07 2021 +0100

    Servlet API changes required to support errorOnELNotFound
---
 java/jakarta/servlet/descriptor/JspPropertyGroupDescriptor.java | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/java/jakarta/servlet/descriptor/JspPropertyGroupDescriptor.java b/java/jakarta/servlet/descriptor/JspPropertyGroupDescriptor.java
index a1c5356..afa6e8c 100644
--- a/java/jakarta/servlet/descriptor/JspPropertyGroupDescriptor.java
+++ b/java/jakarta/servlet/descriptor/JspPropertyGroupDescriptor.java
@@ -40,6 +40,14 @@ public interface JspPropertyGroupDescriptor {
     public String getElIgnored();
 
     /**
+     * Will the use of an unknown identifier in EL within a JSP page trigger an
+     * error for this group?
+     *
+     * @return {@code true} if an error will be triggered, otherwise {@code false}
+     */
+    public String getErrorOnELNotFound();
+
+    /**
      * Obtain the page encoding for this group.
      *
      * @return the page encoding for this group

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org