All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jakarta.servlet.jsp.el.ScopedAttributeELResolver Maven / Gradle / Ivy

There is a newer version: 11.0.0-M4
Show newest version
/*
 * Copyright (c) 1997, 2020 Oracle and/or its affiliates and others.
 * All rights reserved.
 * Copyright 2004 The Apache Software Foundation
 *
 * Licensed 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 jakarta.servlet.jsp.el;

import java.beans.FeatureDescriptor;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.Enumeration;

import jakarta.servlet.jsp.PageContext;
import jakarta.servlet.jsp.JspContext;

import jakarta.el.ELContext;
import jakarta.el.ELClass;
import jakarta.el.ELResolver;
import jakarta.el.ELException;

/**
 * Defines variable resolution behavior for scoped attributes.
 *
 * 

* This resolver handles all variable resolutions (where base is null. It searches * PageContext.findAttribute() for a matching attribute. If not found, it will return null, or * in the case of setValue it will create a new attribute in the page scope with the given name. *

* * @see jakarta.el.ELResolver * @since JSP 2.1 */ public class ScopedAttributeELResolver extends ELResolver { /** * If the base object is null, searches the page, request, session and application scopes for an * attribute with the given name and returns it, or null if no attribute exists with the current name. * *

* The propertyResolved property of the ELContext object must be set to true * by this resolver before returning if base is null. If this property is not true after * this method is called, the caller should ignore the return value. *

* * @param context The context of this evaluation. * @param base Only null is handled by this resolver. Other values will result in an immediate * return. * @param property The name of the scoped attribute to resolve. * @return If the propertyResolved property of ELContext was set to true, * then the scoped attribute; otherwise undefined. * @throws NullPointerException if context is null * @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. */ @Override public Object getValue(ELContext context, Object base, Object property) { if (context == null) { throw new NullPointerException(); } if (base == null) { context.setPropertyResolved(true); if (property instanceof String) { String attribute = (String) property; PageContext ctxt = (PageContext) context.getContext(JspContext.class); Object value = ctxt.findAttribute(attribute); // To support reference of static fields for imported class in // EL 3.0, if a scoped attribute returns null, this attribute // is further checked to see if it is the name of an imported // class. If so, an ELClass instance is returned. // Note: the JSP spec needs to be updated for this behavior. Note // also that this behavior is not backward compatible with JSP 2.2 // and a runtime switch may be needed to force backward // compatility. if (value == null) { // check to see if the property is an imported class if (context.getImportHandler() != null) { Class c = context.getImportHandler().resolveClass(attribute); if (c != null) { value = new ELClass(c); // A possible optimization is to set the ELClass // instance in an attribute map. } } } return value; } } return null; } /** * If the base object is null, returns Object.class to indicate that any type is valid to * set for a scoped attribute. * *

* The propertyResolved property of the ELContext object must be set to true * by this resolver before returning if base is null. If this property is not true after * this method is called, the caller should ignore the return value. *

* * @param context The context of this evaluation. * @param base Only null is handled by this resolver. Other values will result in an immediate * return. * @param property The name of the scoped attribute to resolve. * @return If the propertyResolved property of ELContext was set to true, * then Object.class; otherwise undefined. * @throws NullPointerException if context is null * @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. */ @Override public Class getType(ELContext context, Object base, Object property) { if (context == null) { throw new NullPointerException(); } if (base == null) { context.setPropertyResolved(true); return Object.class; } return null; } /** * If the base object is null, sets an existing scoped attribute to the new value, or creates a new * scoped attribute if one does not exist by this name. * *

* If the provided attribute name matches the key of an attribute in page scope, request scope, session scope, or * application scope, the corresponding attribute value will be replaced by the provided value. Otherwise, a new * page scope attribute will be created with the given name and value. *

* *

* The propertyResolved property of the ELContext object must be set to true * by this resolver before returning if base is null. If this property is not true after * this method is called, the caller should ignore the return value. *

* * @param context The context of this evaluation. * @param base Only null is handled by this resolver. Other values will result in an immediate * return. * @param property The name of the scoped attribute to set. * @param val The value for the scoped attribute. * @throws NullPointerException if context is null. * @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. */ @Override public void setValue(ELContext context, Object base, Object property, Object val) { if (context == null) { throw new NullPointerException(); } if (base == null) { context.setPropertyResolved(true); if (property instanceof String) { PageContext ctxt = (PageContext) context.getContext(JspContext.class); String attr = (String) property; if (ctxt.getAttribute(attr, PageContext.REQUEST_SCOPE) != null) ctxt.setAttribute(attr, val, PageContext.REQUEST_SCOPE); else if (ctxt.getAttribute(attr, PageContext.SESSION_SCOPE) != null) ctxt.setAttribute(attr, val, PageContext.SESSION_SCOPE); else if (ctxt.getAttribute(attr, PageContext.APPLICATION_SCOPE) != null) ctxt.setAttribute(attr, val, PageContext.APPLICATION_SCOPE); else { ctxt.setAttribute(attr, val, PageContext.PAGE_SCOPE); } } } } /** * If the base object is null, returns false to indicate that scoped attributes are never * read-only. * *

* The propertyResolved property of the ELContext object must be set to true * by this resolver before returning if base is null. If this property is not true after * this method is called, the caller should ignore the return value. *

* * @param context The context of this evaluation. * @param base Only null is handled by this resolver. Other values will result in an immediate * return. * @param property The name of the scoped attribute. * @return If the propertyResolved property of ELContext was set to true, * then false; otherwise undefined. * @throws NullPointerException if context is null. * @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. */ @Override public boolean isReadOnly(ELContext context, Object base, Object property) { if (context == null) { throw new NullPointerException(); } if (base == null) { context.setPropertyResolved(true); } return false; } /** * If the base object is null, returns an Iterator containing * FeatureDescriptor objects with information about each scoped attribute resolved by this resolver. * Otherwise, returns null. * *

* The Iterator returned must contain one instance of {@link java.beans.FeatureDescriptor} for each * scoped attribute found in any scope. Each info object contains information about a single scoped attribute, and * is initialized as follows: *

* *
*
displayName
- The name of the scoped attribute.
*
name
- Same as displayName property.
*
shortDescription
- A suitable description for the scoped attribute. Should include the attribute's current * scope (page, request, session, application). Will vary by implementation.
*
expert
- false
*
hidden
- false
*
preferred
- true
*
* In addition, the following named attributes must be set in the returned FeatureDescriptors: *
*
{@link ELResolver#TYPE}
- The current runtime type of the scoped attribute.
*
{@link ELResolver#RESOLVABLE_AT_DESIGN_TIME}
- true.
*
* * @param context The context of this evaluation. * @param base Only null is handled by this resolver. Other values will result in a * null return value. * @return An Iterator containing one FeatureDescriptor object for each scoped attribute, * or null if base is not null. */ @Override public Iterator getFeatureDescriptors(ELContext context, Object base) { Enumeration attrs; ArrayList list = new ArrayList<>(); PageContext ctxt = (PageContext) context.getContext(JspContext.class); attrs = ctxt.getAttributeNamesInScope(PageContext.PAGE_SCOPE); while (attrs.hasMoreElements()) { String name = attrs.nextElement(); Object value = ctxt.getAttribute(name, PageContext.PAGE_SCOPE); FeatureDescriptor descriptor = new FeatureDescriptor(); descriptor.setName(name); descriptor.setDisplayName(name); descriptor.setShortDescription("page scope attribute"); descriptor.setExpert(false); descriptor.setHidden(false); descriptor.setPreferred(true); descriptor.setValue("type", value.getClass()); descriptor.setValue("resolvableAtDesignTime", Boolean.TRUE); list.add(descriptor); } attrs = ctxt.getAttributeNamesInScope(PageContext.REQUEST_SCOPE); while (attrs.hasMoreElements()) { String name = attrs.nextElement(); Object value = ctxt.getAttribute(name, PageContext.REQUEST_SCOPE); FeatureDescriptor descriptor = new FeatureDescriptor(); descriptor.setName(name); descriptor.setDisplayName(name); descriptor.setShortDescription("request scope attribute"); descriptor.setExpert(false); descriptor.setHidden(false); descriptor.setPreferred(true); descriptor.setValue("type", value.getClass()); descriptor.setValue("resolvableAtDesignTime", Boolean.TRUE); list.add(descriptor); } attrs = ctxt.getAttributeNamesInScope(PageContext.SESSION_SCOPE); while (attrs.hasMoreElements()) { String name = attrs.nextElement(); Object value = ctxt.getAttribute(name, PageContext.SESSION_SCOPE); FeatureDescriptor descriptor = new FeatureDescriptor(); descriptor.setName(name); descriptor.setDisplayName(name); descriptor.setShortDescription("session scope attribute"); descriptor.setExpert(false); descriptor.setHidden(false); descriptor.setPreferred(true); descriptor.setValue("type", value.getClass()); descriptor.setValue("resolvableAtDesignTime", Boolean.TRUE); list.add(descriptor); } attrs = ctxt.getAttributeNamesInScope(PageContext.APPLICATION_SCOPE); while (attrs.hasMoreElements()) { String name = attrs.nextElement(); Object value = ctxt.getAttribute(name, PageContext.APPLICATION_SCOPE); FeatureDescriptor descriptor = new FeatureDescriptor(); descriptor.setName(name); descriptor.setDisplayName(name); descriptor.setShortDescription("application scope attribute"); descriptor.setExpert(false); descriptor.setHidden(false); descriptor.setPreferred(true); descriptor.setValue("type", value.getClass()); descriptor.setValue("resolvableAtDesignTime", Boolean.TRUE); list.add(descriptor); } return list.iterator(); } /** * If the base object is null, returns String.class. Otherwise, returns null. * * @param context The context of this evaluation. * @param base Only null is handled by this resolver. Other values will result in a * null return value. * @return null if base is not null; otherwise String.class. */ @Override public Class getCommonPropertyType(ELContext context, Object base) { if (base == null) { return String.class; } return null; } }