jakarta.el.ExpressionFactory Maven / Gradle / Ivy
/*
* 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.el;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Properties;
/**
* Provides an implementation for creating and evaluating Jakarta Expression Language expressions.
*
*
* Classes that implement the Jakarta Expression Language expression language expose their functionality via this
* abstract class. An implementation supports the following functionalities.
*
*
* - Parses a
String
into a {@link ValueExpression} or {@link MethodExpression} instance for later
* evaluation.
* - Implements an
ELResolver
for query operators
* - Provides a default type coercion
*
*
*
* The {@link #newInstance} method can be used to obtain an instance of the implementation. Technologies such as
* Jakarta Server Pages and Jakarta Faces provide access to an implementation via factory methods.
*
*
* The {@link #createValueExpression} method is used to parse expressions that evaluate to values (both l-values and
* r-values are supported). The {@link #createMethodExpression} method is used to parse expressions that evaluate to a
* reference to a method on an object.
*
*
* Resolution of model objects is performed at evaluation time, via the {@link ELResolver} associated with the
* {@link ELContext} passed to the ValueExpression
or MethodExpression
.
*
*
* The ELContext object also provides access to the {@link FunctionMapper} and {@link VariableMapper} to be used when
* parsing the expression. Jakarta Expression Language function and variable mapping is performed at parse-time, and the
* results are bound to the expression. Therefore, the {@link ELContext}, {@link FunctionMapper}, and
* {@link VariableMapper} are not stored for future use and do not have to be Serializable
.
*
*
* The createValueExpression
and createMethodExpression
methods must be thread-safe. That is,
* multiple threads may call these methods on the same ExpressionFactory
object simultaneously.
* Implementations should synchronize access if they depend on transient state. Implementations should not, however,
* assume that only one object of each ExpressionFactory
type will be instantiated; global caching should
* therefore be static.
*
*
* The ExpressionFactory
must be able to handle the following types of input for the
* expression
parameter:
*
* - Single expressions using the
${}
delimiter (e.g. "${employee.lastName}"
).
* - Single expressions using the
#{}
delimiter (e.g. "#{employee.lastName}"
).
* - Literal text containing no
${}
or #{}
delimiters (e.g. "John Doe"
).
* - Multiple expressions using the same delimiter (e.g.
"${employee.firstName}${employee.lastName}"
or
* "#{employee.firstName}#{employee.lastName}"
).
* - Mixed literal text and expressions using the same delimiter (e.g.
*
"Name: ${employee.firstName} ${employee.lastName}"
).
*
*
*
* The following types of input are illegal and must cause an {@link ELException} to be thrown:
*
* - Multiple expressions using different delimiters (e.g.
*
"${employee.firstName}#{employee.lastName}"
).
* - Mixed literal text and expressions using different delimiters(e.g.
*
"Name: ${employee.firstName} #{employee.lastName}"
).
*
*
* @since Jakarta Server Pages 2.1
*/
public abstract class ExpressionFactory {
/**
* Creates a new instance of a ExpressionFactory
. This method uses the following ordered lookup procedure
* to determine the ExpressionFactory
implementation class to load:
*
*
* - Use the Services API (as detailed in the JAR specification). If a resource with the name of
*
META-INF/services/jakarta.el.ExpressionFactory
exists, then its first line, if present, is used as the
* UTF-8 encoded name of the implementation class.
* - Use the properties file "lib/el.properties" in the JRE directory. If this file exists and it is readable by the
*
java.util.Properties.load(InputStream)
method, and it contains an entry whose key is
* "jakarta.el.ExpressionFactory", then the value of that entry is used as the name of the implementation class.
* - Use the
jakarta.el.ExpressionFactory
system property. If a system property with this name is defined,
* then its value is used as the name of the implementation class.
* - Use a platform default implementation.
*
*
* @return a new ExpressionFactory
instance
*/
public static ExpressionFactory newInstance() {
return ExpressionFactory.newInstance(null);
}
/**
* Create a new instance of a ExpressionFactory
, with optional properties.
*
*
* This method uses the same lookup procedure as the one used in newInstance()
.
*
*
* If the argument properties
is not null, and if the implementation contains a constructor with a single
* parameter of type java.util.Properties
, then the constructor is used to create the instance.
*
*
* Properties are optional and can be ignored by an implementation.
*
*
* The name of a property should start with "jakarta.el."
*
*
* The following are some suggested names for properties.
*
* - jakarta.el.cacheSize
*
*
* @param properties Properties passed to the implementation. If null, then no properties.
*
* @return a new ExpressionFactory
instance
*/
public static ExpressionFactory newInstance(Properties properties) {
return (ExpressionFactory) FactoryFinder.find(ExpressionFactory.class,
"jakarta.el.ExpressionFactory", "com.sun.el.ExpressionFactoryImpl", properties);
}
/**
* Parses an expression into a {@link ValueExpression} for later evaluation. Use this method for expressions that refer
* to values.
*
*
* This method should perform syntactic validation of the expression. If in doing so it detects errors, it should raise
* an ELException
.
*
* @param context The Jakarta Expression Language context used to parse the expression. The FunctionMapper
* and VariableMapper
stored in the ELContext are used to resolve functions and variables found in the
* expression. They can be null
, in which case functions or variables are not supported for this
* expression. The object returned must invoke the same functions and access the same variable mappings regardless of
* whether the mappings in the provided FunctionMapper
and VariableMapper
instances change
* between calling ExpressionFactory.createValueExpression()
and any method on
* ValueExpression
. Note that within Jakarta Expression Language, the ${} and #{} syntaxes are treated
* identically. This includes the use of VariableMapper and FunctionMapper at expression creation time. Each is invoked
* if not null, independent of whether the #{} or ${} syntax is used for the expression.
* @param expression The expression to parse
* @param expectedType The type the result of the expression will be coerced to after evaluation.
*
* @return The parsed expression
*
* @throws NullPointerException Thrown if expectedType is null.
* @throws ELException Thrown if there are syntactical errors in the provided expression.
*/
public abstract ValueExpression createValueExpression(ELContext context, String expression, Class> expectedType);
/**
* Creates a ValueExpression that wraps an object instance.
*
*
* This method can be used to pass any object as a ValueExpression. The wrapper ValueExpression is read only, and
* returns the wrapped object via its getValue()
method, optionally coerced.
*
*
* @param instance The object instance to be wrapped.
* @param expectedType The type the result of the expression will be coerced to after evaluation. There will be no
* coercion if it is Object.class,
* @throws NullPointerException Thrown if expectedType is null.
* @return a ValueExpression that wraps an object instance
*/
public abstract ValueExpression createValueExpression(Object instance, Class> expectedType);
/**
* Parses an expression into a {@link MethodExpression} for later evaluation. Use this method for expressions that refer
* to methods.
*
*
* If the expression is a String literal, a MethodExpression
*
is created, which when invoked, returns the String literal, coerced to expectedReturnType. An ELException is
* thrown if expectedReturnType is void or if the coercion of the String literal to the expectedReturnType yields an
* error (see Section "1.16 Type Conversion").
*
*
* This method should perform syntactic validation of the expression. If in doing so it detects errors, it should raise
* an ELException
.
*
* @param context The Jakarta Expression Language context used to parse the expression. The FunctionMapper
* and VariableMapper
stored in the ELContext are used to resolve functions and variables found in the
* expression. They can be null
, in which case functions or variables are not supported for this
* expression. The object returned must invoke the same functions and access the same variable mappings regardless of
* whether the mappings in the provided FunctionMapper
and VariableMapper
instances change
* between calling ExpressionFactory.createMethodExpression()
and any method on
* MethodExpression
. Note that within the EL, the ${} and #{} syntaxes are treated identically. This
* includes the use of VariableMapper and FunctionMapper at expression creation time. Each is invoked if not null,
* independent of whether the #{} or ${} syntax is used for the expression.
* @param expression The expression to parse
* @param expectedReturnType The expected return type for the method to be found. After evaluating the expression, the
* MethodExpression
must check that the return type of the actual method matches this type. Passing in a
* value of null
indicates the caller does not care what the return type is, and the check is disabled.
* @param expectedParamTypes The expected parameter types for the method to be found. Must be an array with no elements
* if there are no parameters expected. It is illegal to pass null
, unless the method is specified with
* arguments in the Jakarta Expression Language expression, in which case these arguments are used for method selection,
* and this parameter is ignored.
*
* @return The parsed expression
*
* @throws ELException Thrown if there are syntactical errors in the provided expression.
* @throws NullPointerException if paramTypes is null
.
*/
public abstract MethodExpression createMethodExpression(ELContext context, String expression, Class> expectedReturnType, Class>[] expectedParamTypes);
/**
* Coerces an object to a specific type according to the Jakarta Expression Language type conversion rules. The custom
* type conversions in the ELResolver
s are not considered.
*
*
* An ELException
is thrown if an error results from applying the conversion rules.
*
* @param obj The object to coerce.
* @param targetType The target type for the coercion.
*
* @return an object coerced to targetType
*
* @throws ELException thrown if an error results from applying the conversion rules.
*/
public abstract Object coerceToType(Object obj, Class> targetType);
/**
* Retrieves an ELResolver that implements the operations in collections.
*
*
* This ELResolver resolves the method invocation on the pair (base
, property
) when
* base
is a Collection
or a Map
, and property
is the name of the
* operation.
*
*
* See the specification document for detailed descriptions of these operators, their arguments, and return values.
*
* @return The ELResolver
that implements the Query Operators.
*
* @since Jakarta Expression Language 3.0
*/
public ELResolver getStreamELResolver() {
return null;
}
/**
* Retrieve a function map containing a pre-configured function mapping.
*
* @return A initial map for functions, null if there is none.
*
* @since Jakarta Expression Language 3.0
*/
public Map getInitFunctionMap() {
return null;
}
}