Skip to content

Package: ELResolver

ELResolver

nameinstructionbranchcomplexitylinemethod
ELResolver()
M: 3 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
convertToType(ELContext, Object, Class)
M: 2 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
getFeatureDescriptors(ELContext, Object)
M: 2 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
invoke(ELContext, Object, Object, Class[], Object[])
M: 2 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%

Coverage

1: /*
2: * Copyright (c) 1997, 2021 Oracle and/or its affiliates and others.
3: * All rights reserved.
4: * Copyright 2004 The Apache Software Foundation
5: *
6: * Licensed under the Apache License, Version 2.0 (the "License");
7: * you may not use this file except in compliance with the License.
8: * You may obtain a copy of the License at
9: *
10: * http://www.apache.org/licenses/LICENSE-2.0
11: *
12: * Unless required by applicable law or agreed to in writing, software
13: * distributed under the License is distributed on an "AS IS" BASIS,
14: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15: * See the License for the specific language governing permissions and
16: * limitations under the License.
17: */
18:
19: package jakarta.el;
20:
21: import java.beans.FeatureDescriptor;
22: import java.util.Iterator;
23:
24: /**
25: * Enables customization of variable, property, method call, and type conversion resolution behavior for Jakarta
26: * Expression Language expression evaluation.
27: *
28: * <p>
29: * While evaluating an expression, the <code>ELResolver</code> associated with the {@link ELContext} is consulted to do
30: * the initial resolution of the first variable of an expression. It is also consulted when a <code>.</code> or
31: * <code>[]</code> operator is encountered.
32: *
33: * <p>
34: * For example, in the Jakarta Expression Language expression <code>${employee.lastName}</code>, the
35: * <code>ELResolver</code> determines what object <code>employee</code> refers to, and what it means to get the
36: * <code>lastName</code> property on that object.
37: *
38: * <p>
39: * Most methods in this class accept a <code>base</code> and <code>property</code> parameter. In the case of variable
40: * resolution (e.g. determining what <code>employee</code> refers to in <code>${employee.lastName}</code>), the
41: * <code>base</code> parameter will be <code>null</code> and the <code>property</code> parameter will always be of type
42: * <code>String</code>. In this case, if the <code>property</code> is not a <code>String</code>, the behavior of the
43: * <code>ELResolver</code> is undefined.
44: *
45: * <p>
46: * In the case of property resolution, the <code>base</code> parameter identifies the base object and the
47: * <code>property</code> object identifies the property on that base. For example, in the expression
48: * <code>${employee.lastName}</code>, <code>base</code> is the result of the variable resolution for
49: * <code>employee</code> and <code>property</code> is the string <code>"lastName"</code>. In the expression
50: * <code>${y[x]}</code>, <code>base</code> is the result of the variable resolution for <code>y</code> and
51: * <code>property</code> is the result of the variable resolution for <code>x</code>.
52: *
53: * <p>
54: * In the case of method call resolution, the <code>base</code> parameter identifies the base object and the
55: * <code>method</code> parameter identifies a method on that base. In the case of overloaded methods, the <code>
56: * paramTypes</code> parameter can be optionally used to identify a method. The <code>params</code>parameter are the
57: * parameters for the method call, and can also be used for resolving overloaded methods when the
58: * <code>paramTypes</code> parameter is not specified.
59: *
60: * <p>
61: * In the case of type conversion resolution, the <code>obj</code> parameter identifies the source object and the
62: * <code>targetType</code> parameter identifies the target type the source to covert to.
63: *
64: * <p>
65: * Though only a single <code>ELResolver</code> is associated with an <code>ELContext</code>, there are usually multiple
66: * resolvers considered for any given variable or property resolution. <code>ELResolver</code>s are combined together
67: * using {@link CompositeELResolver}s, to define rich semantics for evaluating an expression.
68: * </p>
69: *
70: * <p>
71: * For the {@link #getValue}, {@link #getType}, {@link #setValue}, and {@link #isReadOnly} methods, an
72: * <code>ELResolver</code> is not responsible for resolving all possible (base, property) pairs. In fact, most resolvers
73: * will only handle a <code>base</code> of a single type. To indicate that a resolver has successfully resolved a
74: * particular (base, property) pair, it must set the <code>propertyResolved</code> property of the
75: * <code>ELContext</code> to <code>true</code>. If it could not handle the given pair, it must leave this property
76: * alone. The caller must ignore the return value of the method if <code>propertyResolved</code> is <code>false</code>.
77: *
78: * <p>
79: * Similarly, for the {@link #convertToType} method an <code>ELResolver</code> must set the
80: * <code>propertyResolved</code> to <code>true</code> to indicate that it handles the conversion of the object to the
81: * target type.
82: *
83: * <p>
84: * The {@link #getFeatureDescriptors} and {@link #getCommonPropertyType} methods are primarily designed for design-time
85: * tool support, but must handle invocation at runtime as well. The {@link java.beans.Beans#isDesignTime} method can be
86: * used to determine if the resolver is being consulted at design-time or runtime.
87: *
88: * @see CompositeELResolver
89: * @see ELContext#getELResolver
90: * @since Jakarta Server Pages 2.1
91: */
92: public abstract class ELResolver {
93:
94: // --------------------------------------------------------- Constants
95:
96: /**
97: * The attribute name of the named attribute in the <code>FeatureDescriptor</code> that specifies the runtime type of
98: * the variable or property.
99: */
100: public static final String TYPE = "type";
101:
102: /**
103: * The attribute name of the named attribute in the <code>FeatureDescriptor</code> that specifies whether the variable
104: * or property can be resolved at runtime.
105: */
106: public static final String RESOLVABLE_AT_DESIGN_TIME = "resolvableAtDesignTime";
107:
108: /**
109: * Attempts to resolve the given <code>property</code> object on the given <code>base</code> object.
110: *
111: * <p>
112: * If this resolver handles the given (base, property) pair, the <code>propertyResolved</code> property of the
113: * <code>ELContext</code> object must be set to <code>true</code> by the resolver, before returning. If this property is
114: * not <code>true</code> after this method is called, the caller should ignore the return value.
115: * </p>
116: *
117: * @param context The context of this evaluation.
118: * @param base The base object whose property value is to be returned, or <code>null</code> to resolve a top-level
119: * variable.
120: * @param property The property or variable to be resolved.
121: *
122: * @return If the <code>propertyResolved</code> property of <code>ELContext</code> was set to <code>true</code>, then
123: * the result of the variable or property resolution; otherwise undefined.
124: *
125: * @throws NullPointerException if context is <code>null</code>
126: * @throws PropertyNotFoundException if the given (base, property) pair is handled by this <code>ELResolver</code> but
127: * the specified variable or property does not exist or is not readable.
128: * @throws ELException if an exception was thrown while performing the property or variable resolution. The thrown
129: * exception must be included as the cause property of this exception, if available.
130: */
131: public abstract Object getValue(ELContext context, Object base, Object property);
132:
133: /**
134: * Attempts to resolve and invoke the given <code>method</code> on the given <code>base</code> object.
135: *
136: * <p>
137: * If this resolver handles the given (base, method) pair, the <code>propertyResolved</code> property of the
138: * <code>ELContext</code> object must be set to <code>true</code> by the resolver, before returning. If this property is
139: * not <code>true</code> after this method is called, the caller should ignore the return value.
140: *
141: * <p>
142: * A default implementation is provided that returns null so that existing classes that extend ELResolver can continue
143: * to function.
144: *
145: * @param context The context of this evaluation.
146: * @param base The bean on which to invoke the method
147: * @param method The simple name of the method to invoke. Will be coerced to a <code>String</code>.
148: * @param paramTypes An array of Class objects identifying the method's formal parameter types, in declared order. Use
149: * an empty array if the method has no parameters. Can be <code>null</code>, in which case the method's formal parameter
150: * types are assumed to be unknown.
151: * @param params The parameters to pass to the method, or <code>null</code> if no parameters.
152: *
153: * @return The result of the method invocation (<code>null</code> if the method has a <code>void</code> return type).
154: *
155: * @throws MethodNotFoundException if no suitable method can be found.
156: * @throws ELException if an exception was thrown while performing (base, method) resolution. The thrown exception must
157: * be included as the cause property of this exception, if available. If the exception thrown is an
158: * <code>InvocationTargetException</code>, extract its <code>cause</code> and pass it to the <code>ELException</code>
159: * constructor.
160: *
161: * @since Jakarta Expression Language 2.2
162: */
163: public Object invoke(ELContext context, Object base, Object method, Class<?>[] paramTypes, Object[] params) {
164: return null;
165: }
166:
167: /**
168: * For a given <code>base</code> and <code>property</code>, attempts to identify the most general type that is
169: * acceptable for an object to be passed as the <code>value</code> parameter in a future call to the {@link #setValue}
170: * method.
171: *
172: * <p>
173: * If this resolver handles the given (base, property) pair, the <code>propertyResolved</code> property of the
174: * <code>ELContext</code> object must be set to <code>true</code> by the resolver, before returning. If this property is
175: * not <code>true</code> after this method is called, the caller should ignore the return value.
176: * </p>
177: *
178: * <p>
179: * This is not always the same as <code>getValue().getClass()</code>. For example, in the case of an
180: * {@link ArrayELResolver}, the <code>getType</code> method will return the element type of the array, which might be a
181: * superclass of the type of the actual element that is currently in the specified array element.
182: * </p>
183: *
184: * <p>
185: * If the resolver or the property is read-only, this method must return {@code null}.
186: * </p>
187: *
188: * @param context The context of this evaluation.
189: * @param base The base object whose property value is to be analyzed, or <code>null</code> to analyze a top-level
190: * variable.
191: * @param property The property or variable to return the acceptable type for.
192: * @return If the <code>propertyResolved</code> property of <code>ELContext</code> was set to <code>true</code>,
193: * the most general acceptable type which must be {@code null} if the either the property or the resolver is
194: * read-only; otherwise undefined
195: * @throws PropertyNotFoundException if the given (base, property) pair is handled by this <code>ELResolver</code> but
196: * the specified variable or property does not exist or is not readable.
197: * @throws ELException if an exception was thrown while performing the property or variable resolution. The thrown
198: * exception must be included as the cause property of this exception, if available.
199: */
200: public abstract Class<?> getType(ELContext context, Object base, Object property);
201:
202: /**
203: * Attempts to set the value of the given <code>property</code> object on the given <code>base</code> object.
204: *
205: * <p>
206: * If this resolver handles the given (base, property) pair, the <code>propertyResolved</code> property of the
207: * <code>ELContext</code> object must be set to <code>true</code> by the resolver, before returning. If this property is
208: * not <code>true</code> after this method is called, the caller can safely assume no value has been set.
209: * </p>
210: *
211: * @param context The context of this evaluation.
212: * @param base The base object whose property value is to be set, or <code>null</code> to set a top-level variable.
213: * @param property The property or variable to be set.
214: * @param value The value to set the property or variable to.
215: * @throws NullPointerException if context is <code>null</code>
216: * @throws PropertyNotFoundException if the given (base, property) pair is handled by this <code>ELResolver</code> but
217: * the specified variable or property does not exist.
218: * @throws PropertyNotWritableException if the given (base, property) pair is handled by this <code>ELResolver</code>
219: * but the specified variable or property is not writable.
220: * @throws ELException if an exception was thrown while attempting to set the property or variable. The thrown exception
221: * must be included as the cause property of this exception, if available.
222: */
223: public abstract void setValue(ELContext context, Object base, Object property, Object value);
224:
225: /**
226: * For a given <code>base</code> and <code>property</code>, attempts to determine whether a call to {@link #setValue}
227: * will always fail.
228: *
229: * <p>
230: * If this resolver handles the given (base, property) pair, the <code>propertyResolved</code> property of the
231: * <code>ELContext</code> object must be set to <code>true</code> by the resolver, before returning. If this property is
232: * not <code>true</code> after this method is called, the caller should ignore the return value.
233: * </p>
234: *
235: * @param context The context of this evaluation.
236: * @param base The base object whose property value is to be analyzed, or <code>null</code> to analyze a top-level
237: * variable.
238: * @param property The property or variable to return the read-only status for.
239: * @return If the <code>propertyResolved</code> property of <code>ELContext</code> was set to <code>true</code>, then
240: * <code>true</code> if the property is read-only or <code>false</code> if not; otherwise undefined.
241: * @throws NullPointerException if context is <code>null</code>
242: * @throws PropertyNotFoundException if the given (base, property) pair is handled by this <code>ELResolver</code> but
243: * the specified variable or property does not exist.
244: * @throws ELException if an exception was thrown while performing the property or variable resolution. The thrown
245: * exception must be included as the cause property of this exception, if available.
246: */
247: public abstract boolean isReadOnly(ELContext context, Object base, Object property);
248:
249: /**
250: * Returns information about the set of variables or properties that can be resolved for the given <code>base</code>
251: * object. One use for this method is to assist tools in auto-completion.
252: *
253: * <p>
254: * If the <code>base</code> parameter is <code>null</code>, the resolver must enumerate the list of top-level variables
255: * it can resolve.
256: * </p>
257: *
258: * <p>
259: * The <code>Iterator</code> returned must contain zero or more instances of {@link java.beans.FeatureDescriptor}, in no
260: * guaranteed order. In the case of primitive types such as <code>int</code>, the value <code>null</code> must be
261: * returned. This is to prevent the useless iteration through all possible primitive values. A return value of
262: * <code>null</code> indicates that this resolver does not handle the given <code>base</code> object or that the results
263: * are too complex to represent with this method and the {@link #getCommonPropertyType} method should be used instead.
264: * </p>
265: *
266: * <p>
267: * Each <code>FeatureDescriptor</code> will contain information about a single variable or property. In addition to the
268: * standard properties, the <code>FeatureDescriptor</code> must have two named attributes (as set by the
269: * <code>setValue</code> method):
270: * <ul>
271: * <li>{@link #TYPE} - The value of this named attribute must be an instance of <code>java.lang.Class</code> and specify
272: * the runtime type of the variable or property.</li>
273: * <li>{@link #RESOLVABLE_AT_DESIGN_TIME} - The value of this named attribute must be an instance of
274: * <code>java.lang.Boolean</code> and indicates whether it is safe to attempt to resolve this property at design-time.
275: * For instance, it may be unsafe to attempt a resolution at design time if the <code>ELResolver</code> needs access to
276: * a resource that is only available at runtime and no acceptable simulated value can be provided.</li>
277: * </ul>
278: *
279: * <p>
280: * The caller should be aware that the <code>Iterator</code> returned might iterate through a very large or even
281: * infinitely large set of properties. Care should be taken by the caller to not get stuck in an infinite loop.
282: *
283: * <p>
284: * This is a "best-effort" list. Not all <code>ELResolver</code>s will return completely accurate results, but all must
285: * be callable at both design-time and runtime (i.e. whether or not <code>Beans.isDesignTime()</code> returns
286: * <code>true</code>), without causing errors.
287: *
288: * <p>
289: * The <code>propertyResolved</code> property of the <code>ELContext</code> is not relevant to this method. The results
290: * of all <code>ELResolver</code>s are concatenated in the case of composite resolvers.
291: *
292: * <p>
293: * The default implementation in {@link ELResolver} returns {@code null}. Sub-classes may wish to over-ride this
294: * method.
295: *
296: * @param context The context of this evaluation.
297: * @param base The base object whose set of valid properties is to be enumerated, or <code>null</code> to enumerate the
298: * set of top-level variables that this resolver can evaluate.
299: * @return An <code>Iterator</code> containing zero or more (possibly infinitely more) <code>FeatureDescriptor</code>
300: * objects, or <code>null</code> if this resolver does not handle the given <code>base</code> object or that the results
301: * are too complex to represent with this method
302: * @see java.beans.FeatureDescriptor
303: *
304: * @deprecated This method will be removed without replacement in EL 6.0
305: */
306: @Deprecated(forRemoval = true, since = "5.0")
307: public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context, Object base) {
308: return null;
309: }
310:
311: /**
312: * Returns the most general type that this resolver accepts for the <code>property</code> argument, given a
313: * <code>base</code> object. One use for this method is to assist tools in auto-completion.
314: *
315: * <p>
316: * This assists tools in auto-completion and also provides a way to express that the resolver accepts a primitive value,
317: * such as an integer index into an array. For example, the {@link ArrayELResolver} will accept any <code>int</code> as
318: * a <code>property</code>, so the return value would be <code>Integer.class</code>.
319: * </p>
320: *
321: * @param context The context of this evaluation.
322: * @param base The base object to return the most general property type for, or <code>null</code> to enumerate the set
323: * of top-level variables that this resolver can evaluate.
324: * @return <code>null</code> if this <code>ELResolver</code> does not know how to handle the given <code>base</code>
325: * object; otherwise <code>Object.class</code> if any type of <code>property</code> is accepted; otherwise the most
326: * general <code>property</code> type accepted for the given <code>base</code>.
327: */
328: public abstract Class<?> getCommonPropertyType(ELContext context, Object base);
329:
330: /**
331: * Converts an object to a specific type.
332: *
333: * <p>
334: * An <code>ELException</code> is thrown if an error occurs during the conversion.
335: * </p>
336: *
337: * @param context The context of this evaluation.
338: * @param obj The object to convert.
339: * @param targetType The target type for the conversion.
340: * @return object converted to <code>targetType</code>
341: * @throws ELException thrown if errors occur.
342: */
343: public <T> T convertToType(ELContext context, Object obj, Class<T> targetType) {
344: return null;
345: }
346: }