Package: ELResolver
ELResolver
name | instruction | branch | complexity | line | method | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
ELResolver() |
|
|
|
|
|
||||||||||||||||||||
convertToType(ELContext, Object, Class) |
|
|
|
|
|
||||||||||||||||||||
getFeatureDescriptors(ELContext, Object) |
|
|
|
|
|
||||||||||||||||||||
invoke(ELContext, Object, Object, Class[], Object[]) |
|
|
|
|
|
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: * @param context The context of this evaluation.
185: * @param base The base object whose property value is to be analyzed, or <code>null</code> to analyze a top-level
186: * variable.
187: * @param property The property or variable to return the acceptable type for.
188: * @return If the <code>propertyResolved</code> property of <code>ELContext</code> was set to <code>true</code>, then
189: * the most general acceptable type; otherwise undefined.
190: * @throws PropertyNotFoundException if the given (base, property) pair is handled by this <code>ELResolver</code> but
191: * the specified variable or property does not exist or is not readable.
192: * @throws ELException if an exception was thrown while performing the property or variable resolution. The thrown
193: * exception must be included as the cause property of this exception, if available.
194: */
195: public abstract Class<?> getType(ELContext context, Object base, Object property);
196:
197: /**
198: * Attempts to set the value of the given <code>property</code> object on the given <code>base</code> object.
199: *
200: * <p>
201: * If this resolver handles the given (base, property) pair, the <code>propertyResolved</code> property of the
202: * <code>ELContext</code> object must be set to <code>true</code> by the resolver, before returning. If this property is
203: * not <code>true</code> after this method is called, the caller can safely assume no value has been set.
204: * </p>
205: *
206: * @param context The context of this evaluation.
207: * @param base The base object whose property value is to be set, or <code>null</code> to set a top-level variable.
208: * @param property The property or variable to be set.
209: * @param value The value to set the property or variable to.
210: * @throws NullPointerException if context is <code>null</code>
211: * @throws PropertyNotFoundException if the given (base, property) pair is handled by this <code>ELResolver</code> but
212: * the specified variable or property does not exist.
213: * @throws PropertyNotWritableException if the given (base, property) pair is handled by this <code>ELResolver</code>
214: * but the specified variable or property is not writable.
215: * @throws ELException if an exception was thrown while attempting to set the property or variable. The thrown exception
216: * must be included as the cause property of this exception, if available.
217: */
218: public abstract void setValue(ELContext context, Object base, Object property, Object value);
219:
220: /**
221: * For a given <code>base</code> and <code>property</code>, attempts to determine whether a call to {@link #setValue}
222: * will always fail.
223: *
224: * <p>
225: * If this resolver handles the given (base, property) pair, the <code>propertyResolved</code> property of the
226: * <code>ELContext</code> object must be set to <code>true</code> by the resolver, before returning. If this property is
227: * not <code>true</code> after this method is called, the caller should ignore the return value.
228: * </p>
229: *
230: * @param context The context of this evaluation.
231: * @param base The base object whose property value is to be analyzed, or <code>null</code> to analyze a top-level
232: * variable.
233: * @param property The property or variable to return the read-only status for.
234: * @return If the <code>propertyResolved</code> property of <code>ELContext</code> was set to <code>true</code>, then
235: * <code>true</code> if the property is read-only or <code>false</code> if not; otherwise undefined.
236: * @throws NullPointerException if context is <code>null</code>
237: * @throws PropertyNotFoundException if the given (base, property) pair is handled by this <code>ELResolver</code> but
238: * the specified variable or property does not exist.
239: * @throws ELException if an exception was thrown while performing the property or variable resolution. The thrown
240: * exception must be included as the cause property of this exception, if available.
241: */
242: public abstract boolean isReadOnly(ELContext context, Object base, Object property);
243:
244: /**
245: * Returns information about the set of variables or properties that can be resolved for the given <code>base</code>
246: * object. One use for this method is to assist tools in auto-completion.
247: *
248: * <p>
249: * If the <code>base</code> parameter is <code>null</code>, the resolver must enumerate the list of top-level variables
250: * it can resolve.
251: * </p>
252: *
253: * <p>
254: * The <code>Iterator</code> returned must contain zero or more instances of {@link java.beans.FeatureDescriptor}, in no
255: * guaranteed order. In the case of primitive types such as <code>int</code>, the value <code>null</code> must be
256: * returned. This is to prevent the useless iteration through all possible primitive values. A return value of
257: * <code>null</code> indicates that this resolver does not handle the given <code>base</code> object or that the results
258: * are too complex to represent with this method and the {@link #getCommonPropertyType} method should be used instead.
259: * </p>
260: *
261: * <p>
262: * Each <code>FeatureDescriptor</code> will contain information about a single variable or property. In addition to the
263: * standard properties, the <code>FeatureDescriptor</code> must have two named attributes (as set by the
264: * <code>setValue</code> method):
265: * <ul>
266: * <li>{@link #TYPE} - The value of this named attribute must be an instance of <code>java.lang.Class</code> and specify
267: * the runtime type of the variable or property.</li>
268: * <li>{@link #RESOLVABLE_AT_DESIGN_TIME} - The value of this named attribute must be an instance of
269: * <code>java.lang.Boolean</code> and indicates whether it is safe to attempt to resolve this property at design-time.
270: * For instance, it may be unsafe to attempt a resolution at design time if the <code>ELResolver</code> needs access to
271: * a resource that is only available at runtime and no acceptable simulated value can be provided.</li>
272: * </ul>
273: *
274: * <p>
275: * The caller should be aware that the <code>Iterator</code> returned might iterate through a very large or even
276: * infinitely large set of properties. Care should be taken by the caller to not get stuck in an infinite loop.
277: *
278: * <p>
279: * This is a "best-effort" list. Not all <code>ELResolver</code>s will return completely accurate results, but all must
280: * be callable at both design-time and runtime (i.e. whether or not <code>Beans.isDesignTime()</code> returns
281: * <code>true</code>), without causing errors.
282: *
283: * <p>
284: * The <code>propertyResolved</code> property of the <code>ELContext</code> is not relevant to this method. The results
285: * of all <code>ELResolver</code>s are concatenated in the case of composite resolvers.
286: *
287: * <p>
288: * The default implementation in {@link ELResolver} returns {@code null}. Sub-classes may wish to over-ride this
289: * method.
290: *
291: * @param context The context of this evaluation.
292: * @param base The base object whose set of valid properties is to be enumerated, or <code>null</code> to enumerate the
293: * set of top-level variables that this resolver can evaluate.
294: * @return An <code>Iterator</code> containing zero or more (possibly infinitely more) <code>FeatureDescriptor</code>
295: * objects, or <code>null</code> if this resolver does not handle the given <code>base</code> object or that the results
296: * are too complex to represent with this method
297: * @see java.beans.FeatureDescriptor
298: *
299: * @deprecated This method will be removed without replacement in EL 6.0
300: */
301: @Deprecated(forRemoval = true, since = "5.0")
302: public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context, Object base) {
303: return null;
304: }
305:
306: /**
307: * Returns the most general type that this resolver accepts for the <code>property</code> argument, given a
308: * <code>base</code> object. One use for this method is to assist tools in auto-completion.
309: *
310: * <p>
311: * This assists tools in auto-completion and also provides a way to express that the resolver accepts a primitive value,
312: * such as an integer index into an array. For example, the {@link ArrayELResolver} will accept any <code>int</code> as
313: * a <code>property</code>, so the return value would be <code>Integer.class</code>.
314: * </p>
315: *
316: * @param context The context of this evaluation.
317: * @param base The base object to return the most general property type for, or <code>null</code> to enumerate the set
318: * of top-level variables that this resolver can evaluate.
319: * @return <code>null</code> if this <code>ELResolver</code> does not know how to handle the given <code>base</code>
320: * object; otherwise <code>Object.class</code> if any type of <code>property</code> is accepted; otherwise the most
321: * general <code>property</code> type accepted for the given <code>base</code>.
322: */
323: public abstract Class<?> getCommonPropertyType(ELContext context, Object base);
324:
325: /**
326: * Converts an object to a specific type.
327: *
328: * <p>
329: * An <code>ELException</code> is thrown if an error occurs during the conversion.
330: * </p>
331: *
332: * @param context The context of this evaluation.
333: * @param obj The object to convert.
334: * @param targetType The target type for the conversion.
335: * @return object converted to <code>targetType</code>
336: * @throws ELException thrown if errors occur.
337: */
338: public <T> T convertToType(ELContext context, Object obj, Class<T> targetType) {
339: return null;
340: }
341: }