From 77eed2e2e3e7e393a31222f18fc86412243aaaa6 Mon Sep 17 00:00:00 2001 From: Mark Thomas Date: Thu, 23 Sep 2021 21:06:08 +0100 Subject: [PATCH] Fix #40. Option to trigger an exception for an unknown EL identifier --- .../servlet/jsp/LocalStrings.properties | 17 +++ .../servlet/jsp/el/NotFoundELResolver.java | 16 +++ spec/src/main/asciidoc/ServerPages.adoc | 117 +++++++++++++++++- 3 files changed, 148 insertions(+), 2 deletions(-) create mode 100644 api/src/main/java/jakarta/servlet/jsp/LocalStrings.properties diff --git a/api/src/main/java/jakarta/servlet/jsp/LocalStrings.properties b/api/src/main/java/jakarta/servlet/jsp/LocalStrings.properties new file mode 100644 index 00000000..0b10c012 --- /dev/null +++ b/api/src/main/java/jakarta/servlet/jsp/LocalStrings.properties @@ -0,0 +1,17 @@ +# +# Copyright (c) 2021 Contributors to the Eclipse Foundation. +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Public License v. 2.0, which is available at +# http://www.eclipse.org/legal/epl-2.0. +# +# This Source Code may also be made available under the following Secondary +# Licenses when the conditions for such availability set forth in the +# Eclipse Public License v. 2.0 are satisfied: GNU General Public License, +# version 2 with the GNU Classpath Exception, which is available at +# https://www.gnu.org/software/classpath/license.html. +# +# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 +# + +el.unknown.identifier=Unknown identifier diff --git a/api/src/main/java/jakarta/servlet/jsp/el/NotFoundELResolver.java b/api/src/main/java/jakarta/servlet/jsp/el/NotFoundELResolver.java index 8efc72eb..7c88e1c0 100644 --- a/api/src/main/java/jakarta/servlet/jsp/el/NotFoundELResolver.java +++ b/api/src/main/java/jakarta/servlet/jsp/el/NotFoundELResolver.java @@ -17,11 +17,13 @@ import java.beans.FeatureDescriptor; import java.util.Iterator; +import java.util.ResourceBundle; import java.util.Collections; import jakarta.el.ELContext; import jakarta.el.ELResolver; import jakarta.el.ELException; +import jakarta.el.PropertyNotFoundException; /** * Defines variable resolution when all other resolvers fail. @@ -30,6 +32,9 @@ */ public class NotFoundELResolver extends ELResolver { + private static final String LSTRING_FILE = "jakarta.servlet.jsp.LocalStrings"; + private static final ResourceBundle lStrings = ResourceBundle.getBundle(LSTRING_FILE); + /** * If the base object is null, searches the Class and static imports for an import with the given name * and returns it if an import exists with the given name. @@ -44,6 +49,11 @@ public class NotFoundELResolver extends ELResolver { * @param property Ignored * @return Always {@code null} * @throws NullPointerException if context is 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}. This is to support + * implementation of the {@code errorOnELNotFound} page/tag directive. * @throws ELException if an exception was thrown while performing the property or variable resolution. The * thrown exception must be included as the cause property of this exception, if * available. @@ -55,6 +65,12 @@ public Object getValue(ELContext context, Object base, Object property) { throw new NullPointerException(); } + 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(true); return null; diff --git a/spec/src/main/asciidoc/ServerPages.adoc b/spec/src/main/asciidoc/ServerPages.adoc index 525aefb6..21f45788 100644 --- a/spec/src/main/asciidoc/ServerPages.adoc +++ b/spec/src/main/asciidoc/ServerPages.adoc @@ -1265,7 +1265,7 @@ XMLTagDefDirectiveBody ::= ( ( 'tag' S TagDirectiveAttrList S? PageDirectiveAttrList ::= ATTR[ language, extends, import, session, buffer, autoFlush, isThreadSafe, info, errorPage, isErrorPage, contentType, pageEncoding, - isELIgnored ] + isELIgnored, errorOnELNotFound ] [ vc: PageDirectiveUniqueAttr ] TagLibDirectiveAttrList ::= ATTR[ !uri, !prefix ] @@ -1276,7 +1276,8 @@ IncludeDirectiveAttrList ::= ATTR[ !file ] TagDirectiveAttrList ::= ATTR[ display-name, body-content, dynamic-attributes, small-icon, large-icon, description, example, - language, import, pageEncoding, isELIgnored ] + language, import, pageEncoding, isELIgnored, + errorOnELNotFound ] [ vc: TagDirectiveUniqueAttr ] AttributeDirectiveAttrList ::= ATTR[ !name, required, fragment, rtexprvalue, @@ -2513,6 +2514,7 @@ page_directive_attr_list ::= { language="scriptingLanguage" } { contentType="ctinfo" } { pageEncoding="peinfo" } { isELIgnored="true|false" } + { errorOnELNotFound="true|false" } { deferredSyntaxAllowedAsLiteral="true|false" } { trimDirectiveWhitespaces="true|false" } ---- @@ -2736,6 +2738,12 @@ attributes. The corresponding JSP configuration element is `el-ignored` varies depending on the `web.xml` version - see <>. +|`errorOnELNotFound` +|Defines whether a `PropertyNotFoundException` is thrown when an EL expression +contains an identifier that the EL machinery cannot resolve. The corresponding +JSP configuration element is `error-on-el-not-found` +(see <<_Unknown_EL_Identifiers>>) + |`deferredSyntax-` + `AllowedAsLiteral` |Indicates if the character sequence #{ is @@ -3758,6 +3766,14 @@ authors, or page authoring groups, may want to follow a methodology where scripting elements are not allowed. See <<_Disabling_Scripting_Elements>> for more details. +=== Unknown EL Identifiers + +The default behaviour of the `NotFoundELResolver` is to return null when +attempting to resolve an unknown identifier. This can mask bugs and therefore +may not always be the desired behaviour. To address this, the default behaviour +can be changed as indicated in +<<_Unknown_EL_Identifiers>> + === Invalid EL Expressions JSP containers are required to produce a @@ -4240,6 +4256,93 @@ delivered using the `.jsp` extension: |=== +[[_Unknown_EL_Identifiers]] +==== Unknown EL Identifiers + +The default behaviour of the `NotFoundELResolver` is to return `null` when +attempting to resolve an unknown identifier. This can mask bugs and therefore +may not always be the desired behaviour. To address this, the default behaviour +can be changed as indicated in this section. + +The default behaviour can be explicitly changed by setting the value of the +`error-on-el-not-found` element. The `error-on-el-not-found` element is a +subelement of `jsp-property-group` (see <<_JSP_Property_Groups>>) +It has no subelements. Its valid values are `true` and `false`. + +For example, the following `web.xml` fragment defines a group that configures +all JSP pages delivered using the `.jsp` extension to throw a +`PropertyNotFoundException` if an EL expression contains an unknown identifier.: + +[source,xml] +---- + + *.jsp + true + +---- + +Page authors can override the default mode through the `errorOnELNotFound` +attribute of the page directive and the `errorOnELNotFound` attribute of the tag +directive can. + +<<_EL_Unknown_Identifier_Settings_for_JSP_Pages>> summarizes the EL unknown +identifier settings for JSP pages, and their meanings: + +[caption='*Table JSP.{jsp-chapter}-{counter:table-number}* '] +[[_EL_Unknown_Identifier_Settings_for_JSP_Pages]] +.EL Evaluation Unknown Identifier for JSP Pages +[cols="30,30,40",options="header"] +|=== + +|JSP Configuration +|Page Directive errorOnELNotFound +|Unknown Identifier Encountered + +|unspecified +|unspecified +|`null` is returned by `ELResolver` + +|false +|unspecified +|`null` is returned by `ELResolver` + +|true +|unspecified +|`PropertyNotFoundException` thrown by `ELResolver` + +|don’t care +|false +|`null` is returned by `ELResolver` + +|don’t care +|true +|`PropertyNotFoundException` thrown by `ELResolver` + +|=== + +<<_EL_Unknown_Identifier_Settings_for_Tag_Files>> summarizes the EL unknown +identifier settings for tag files, and their meanings: + +[caption='*Table JSP.{jsp-chapter}-{counter:table-number}* '] +[[_EL_Unknown_Identifier_Settings_for_Tag_Files]] +.EL Unknown Identifier Settings for Tag Files +[cols="50,50",options="header"] +|=== + +|Tag Directive errorOnELNotFound +|Unknown Identifier Encountered + +|unspecified +|`null` is returned by `ELResolver` + +|false +|`null` is returned by `ELResolver` + +|true +|`PropertyNotFoundException` thrown by `ELResolver` + +|=== + ==== Declaring Page Encodings The JSP configuration element `page-encoding` @@ -8927,6 +9030,7 @@ tag_directive_attr_list ::= { display-name="display-name" } { import="importList" } { pageEncoding="peinfo" } { isELIgnored="true|false" } + { errorOnELNotFound="true|false" } { deferredSyntaxAllowedAsLiteral="true|false" } { trimDirectiveWhitespaces="true|false" } .... @@ -9010,6 +9114,12 @@ semantics of the `isELIgnored` attribute of the `page` directive. However, there is no corresponding global configuration element in `web.xml`. +|`errorOnELNotFound` +|(optional) Carries the same syntax and +semantics of the `errorOnELNotFound` attribute of the `page` directive. +However, there is no corresponding global configuration element in +`web.xml`. + |`deferredSyntax-` + `AllowedAsLiteral` |(optional) Carries the same syntax and @@ -11548,6 +11658,9 @@ Jakarta Server Pages specification. This appendix is non-normative. * Deprecate methods that override `ELResolver.getFeatureDescriptors()` as that method has been deprecated as of EL 5.0. +* https://github.com/eclipse-ee4j/jsp-api/issues/40[#40] + Add an option to raise a `PropertyNotFoundException` when an EL expression + contains an unknown identifier. * https://github.com/eclipse-ee4j/jsp-api/issues/44[#44] Clarify that the EL environment within a JSP has a set of default imports consistent with the default imports for the scripting environment. Refactor