This repository was archived by the owner on Jan 30, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathELResolver.java
More file actions
454 lines (436 loc) · 22.4 KB
/
ELResolver.java
File metadata and controls
454 lines (436 loc) · 22.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2012 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*
*
* This file incorporates work covered by the following copyright and
* permission notice:
*
* 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 javax.el;
import java.util.Iterator;
import java.beans.FeatureDescriptor;
/**
* Enables customization of variable, property, method call, and type
* conversion resolution behavior for EL expression evaluation.
*
* <p>While evaluating an expression, the <code>ELResolver</code> associated
* with the {@link ELContext} is consulted to do the initial resolution of
* the first variable of an expression. It is also consulted when a
* <code>.</code> or <code>[]</code> operator is encountered.
*
* <p>For example, in the EL expression <code>${employee.lastName}</code>,
* the <code>ELResolver</code> determines what object <code>employee</code>
* refers to, and what it means to get the <code>lastName</code> property on
* that object.</p>
*
* <p>Most methods in this class accept a <code>base</code>
* and <code>property</code> parameter. In the case of variable resolution
* (e.g. determining what <code>employee</code> refers to in
* <code>${employee.lastName}</code>), the <code>base</code> parameter will
* be <code>null</code> and the <code>property</code> parameter will always
* be of type <code>String</code>. In this case, if the <code>property</code>
* is not a <code>String</code>, the behavior of the <code>ELResolver</code>
* is undefined.</p>
*
* <p>In the case of property resolution, the <code>base</code> parameter
* identifies the base object and the <code>property</code> object identifies
* the property on that base. For example, in the expression
* <code>${employee.lastName}</code>, <code>base</code> is the result of the
* variable resolution for <code>employee</code> and <code>property</code>
* is the string <code>"lastName"</code>. In the expression
* <code>${y[x]}</code>, <code>base</code> is the result of the variable
* resolution for <code>y</code> and <code>property</code> is the result of
* the variable resolution for <code>x</code>.</p>
*
* <p>In the case of method call resolution, the <code>base</code> parameter
* identifies the base object and the <code>method</code> parameter identifies
* a method on that base. In the case of overloaded methods, the <code>
* paramTypes</code> parameter can be optionally used to identify a method.
* The <code>params</code>parameter are the parameters for the method call,
* and can also be used for resolving overloaded methods when the
* <code>paramTypes</code> parameter is not specified.
*
* <p>In the case of type conversion resolution, the <code>obj</code> parameter
* identifies the source object and the <code>targetType</code> parameter
* identifies the target type the source to covert to.
*
* <p>Though only a single <code>ELResolver</code> is associated with an
* <code>ELContext</code>, there are usually multiple resolvers considered
* for any given variable or property resolution. <code>ELResolver</code>s
* are combined together using {@link CompositeELResolver}s, to define
* rich semantics for evaluating an expression.</p>
*
* <p>For the {@link #getValue}, {@link #getType}, {@link #setValue}, and
* {@link #isReadOnly} methods, an <code>ELResolver</code> is not
* responsible for resolving all possible (base, property) pairs. In fact,
* most resolvers will only handle a <code>base</code> of a single type.
* To indicate that a resolver has successfully resolved a particular
* (base, property) pair, it must set the <code>propertyResolved</code>
* property of the <code>ELContext</code> to <code>true</code>. If it could
* not handle the given pair, it must leave this property alone. The caller
* must ignore the return value of the method if <code>propertyResolved</code>
* is <code>false</code>.</p>
*
* <p>Similarly, for the {@link #convertToType} method an
* <code>ELResolver</code>
* must set the <code>propertyResolved</code> to <code>true</code> to indicate
* that it handles the conversion of the object to the target type.</p>
*
* <p>The {@link #getFeatureDescriptors} and {@link #getCommonPropertyType}
* methods are primarily designed for design-time tool support, but must
* handle invocation at runtime as well. The
* {@link java.beans.Beans#isDesignTime} method can be used to determine
* if the resolver is being consulted at design-time or runtime.</p>
*
* @see CompositeELResolver
* @see ELContext#getELResolver
* @since JSP 2.1
*/
public abstract class ELResolver {
// --------------------------------------------------------- Constants
/**
* <p>The attribute name of the named attribute in the
* <code>FeatureDescriptor</code> that specifies the runtime type of
* the variable or property.</p>
*/
public static final String TYPE = "type";
/**
* <p>The attribute name of the named attribute in the
* <code>FeatureDescriptor</code> that specifies whether the
* variable or property can be resolved at runtime.</p>
*/
public static final String RESOLVABLE_AT_DESIGN_TIME = "resolvableAtDesignTime";
/**
* Attempts to resolve the given <code>property</code> object on the given
* <code>base</code> object.
*
* <p>If this resolver handles the given (base, property) pair,
* the <code>propertyResolved</code> property of the
* <code>ELContext</code> object must be set to <code>true</code>
* by the resolver, before returning. If this property is not
* <code>true</code> after this method is called, the caller should ignore
* the return value.</p>
*
* @param context The context of this evaluation.
* @param base The base object whose property value is to be returned,
* or <code>null</code> to resolve a top-level variable.
* @param property The property or variable to be resolved.
* @return If the <code>propertyResolved</code> property of
* <code>ELContext</code> was set to <code>true</code>, then
* the result of the variable or property resolution; otherwise
* undefined.
* @throws NullPointerException if context is <code>null</code>
* @throws PropertyNotFoundException if the given (base, property) pair
* is handled by this <code>ELResolver</code> but the specified
* variable or property does not exist or is not readable.
* @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.
*/
public abstract Object getValue(ELContext context,
Object base,
Object property);
/**
* Attempts to resolve and invoke the given <code>method</code> on the given
* <code>base</code> object.
*
* <p>If this resolver handles the given (base, method) pair,
* the <code>propertyResolved</code> property of the
* <code>ELContext</code> object must be set to <code>true</code>
* by the resolver, before returning. If this property is not
* <code>true</code> after this method is called, the caller should ignore
* the return value.</p>
*
* <p>A default implementation is provided that returns null so that
* existing classes that extend ELResolver can continue to function.</p>
*
* @param context The context of this evaluation.
* @param base The bean on which to invoke the method
* @param method The simple name of the method to invoke.
* Will be coerced to a <code>String</code>.
* @param paramTypes An array of Class objects identifying the
* method's formal parameter types, in declared order.
* Use an empty array if the method has no parameters.
* Can be <code>null</code>, in which case the method's formal
* parameter types are assumed to be unknown.
* @param params The parameters to pass to the method, or
* <code>null</code> if no parameters.
* @return The result of the method invocation (<code>null</code> if
* the method has a <code>void</code> return type).
* @throws MethodNotFoundException if no suitable method can be found.
* @throws ELException if an exception was thrown while performing
* (base, method) resolution. The thrown exception must be
* included as the cause property of this exception, if
* available. If the exception thrown is an
* <code>InvocationTargetException</code>, extract its
* <code>cause</code> and pass it to the
* <code>ELException</code> constructor.
* @since EL 2.2
*/
public Object invoke(ELContext context,
Object base,
Object method,
Class<?>[] paramTypes,
Object[] params) {
return null;
}
/**
* For a given <code>base</code> and <code>property</code>, attempts to
* identify the most general type that is acceptable for an object to be
* passed as the <code>value</code> parameter in a future call
* to the {@link #setValue} method.
*
* <p>If this resolver handles the given (base, property) pair,
* the <code>propertyResolved</code> property of the
* <code>ELContext</code> object must be set to <code>true</code>
* by the resolver, before returning. If this property is not
* <code>true</code> after this method is called, the caller should ignore
* the return value.</p>
*
* <p>This is not always the same as <code>getValue().getClass()</code>.
* For example, in the case of an {@link ArrayELResolver}, the
* <code>getType</code> method will return the element type of the
* array, which might be a superclass of the type of the actual
* element that is currently in the specified array element.</p>
*
* @param context The context of this evaluation.
* @param base The base object whose property value is to be analyzed,
* or <code>null</code> to analyze a top-level variable.
* @param property The property or variable to return the acceptable
* type for.
* @return If the <code>propertyResolved</code> property of
* <code>ELContext</code> was set to <code>true</code>, then
* the most general acceptable type; otherwise undefined.
* @throws PropertyNotFoundException if the given (base, property) pair
* is handled by this <code>ELResolver</code> but the specified
* variable or property does not exist or is not readable.
* @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.
*/
public abstract Class<?> getType(ELContext context,
Object base,
Object property);
/**
* Attempts to set the value of the given <code>property</code>
* object on the given <code>base</code> object.
*
* <p>If this resolver handles the given (base, property) pair,
* the <code>propertyResolved</code> property of the
* <code>ELContext</code> object must be set to <code>true</code>
* by the resolver, before returning. If this property is not
* <code>true</code> after this method is called, the caller can
* safely assume no value has been set.</p>
*
* @param context The context of this evaluation.
* @param base The base object whose property value is to be set,
* or <code>null</code> to set a top-level variable.
* @param property The property or variable to be set.
* @param value The value to set the property or variable to.
* @throws NullPointerException if context is <code>null</code>
* @throws PropertyNotFoundException if the given (base, property) pair
* is handled by this <code>ELResolver</code> but the specified
* variable or property does not exist.
* @throws PropertyNotWritableException if the given (base, property)
* pair is handled by this <code>ELResolver</code> but the specified
* variable or property is not writable.
* @throws ELException if an exception was thrown while attempting to
* set the property or variable. The thrown exception
* must be included as the cause property of this exception, if
* available.
*/
public abstract void setValue(ELContext context,
Object base,
Object property,
Object value);
/**
* For a given <code>base</code> and <code>property</code>, attempts to
* determine whether a call to {@link #setValue} will always fail.
*
* <p>If this resolver handles the given (base, property) pair,
* the <code>propertyResolved</code> property of the
* <code>ELContext</code> object must be set to <code>true</code>
* by the resolver, before returning. If this property is not
* <code>true</code> after this method is called, the caller should ignore
* the return value.</p>
*
* @param context The context of this evaluation.
* @param base The base object whose property value is to be analyzed,
* or <code>null</code> to analyze a top-level variable.
* @param property The property or variable to return the read-only status
* for.
* @return If the <code>propertyResolved</code> property of
* <code>ELContext</code> was set to <code>true</code>, then
* <code>true</code> if the property is read-only or
* <code>false</code> if not; otherwise undefined.
* @throws NullPointerException if context is <code>null</code>
* @throws PropertyNotFoundException if the given (base, property) pair
* is handled by this <code>ELResolver</code> but the specified
* variable or property does not exist.
* @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.
*/
public abstract boolean isReadOnly(ELContext context,
Object base,
Object property);
/**
* Returns information about the set of variables or properties that
* can be resolved for the given <code>base</code> object. One use for
* this method is to assist tools in auto-completion.
*
* <p>If the <code>base</code> parameter is <code>null</code>, the
* resolver must enumerate the list of top-level variables it can
* resolve.</p>
*
* <p>The <code>Iterator</code> returned must contain zero or more
* instances of {@link java.beans.FeatureDescriptor}, in no guaranteed
* order. In the case of primitive types such as <code>int</code>, the
* value <code>null</code> must be returned. This is to prevent the
* useless iteration through all possible primitive values. A
* return value of <code>null</code> indicates that this resolver does
* not handle the given <code>base</code> object or that the results
* are too complex to represent with this method and the
* {@link #getCommonPropertyType} method should be used instead.</p>
*
* <p>Each <code>FeatureDescriptor</code> will contain information about
* a single variable or property. In addition to the standard
* properties, the <code>FeatureDescriptor</code> must have two
* named attributes (as set by the <code>setValue</code> method):
* <ul>
* <li>{@link #TYPE} - The value of this named attribute must be
* an instance of <code>java.lang.Class</code> and specify the
* runtime type of the variable or property.</li>
* <li>{@link #RESOLVABLE_AT_DESIGN_TIME} - The value of this
* named attribute must be an instance of
* <code>java.lang.Boolean</code> and indicates whether it is safe
* to attempt to resolve this property at design-time. For
* instance, it may be unsafe to attempt a resolution at design
* time if the <code>ELResolver</code> needs access to a resource
* that is only available at runtime and no acceptable simulated
* value can be provided.</li>
* </ul></p>
*
* <p>The caller should be aware that the <code>Iterator</code>
* returned might iterate through a very large or even infinitely large
* set of properties. Care should be taken by the caller to not get
* stuck in an infinite loop.</p>
*
* <p>This is a "best-effort" list. Not all <code>ELResolver</code>s
* will return completely accurate results, but all must be callable
* at both design-time and runtime (i.e. whether or not
* <code>Beans.isDesignTime()</code> returns <code>true</code>),
* without causing errors.</p>
*
* <p>The <code>propertyResolved</code> property of the
* <code>ELContext</code> is not relevant to this method.
* The results of all <code>ELResolver</code>s are concatenated
* in the case of composite resolvers.</p>
*
* @param context The context of this evaluation.
* @param base The base object whose set of valid properties is to
* be enumerated, or <code>null</code> to enumerate the set of
* top-level variables that this resolver can evaluate.
* @return An <code>Iterator</code> containing zero or more (possibly
* infinitely more) <code>FeatureDescriptor</code> objects, or
* <code>null</code> if this resolver does not handle the given
* <code>base</code> object or that the results are too complex to
* represent with this method
* @see java.beans.FeatureDescriptor
*/
public abstract Iterator<FeatureDescriptor> getFeatureDescriptors(
ELContext context,
Object base);
/**
* Returns the most general type that this resolver accepts for the
* <code>property</code> argument, given a <code>base</code> object.
* One use for this method is to assist tools in auto-completion.
*
* <p>This assists tools in auto-completion and also provides a
* way to express that the resolver accepts a primitive value,
* such as an integer index into an array. For example, the
* {@link ArrayELResolver} will accept any <code>int</code> as a
* <code>property</code>, so the return value would be
* <code>Integer.class</code>.</p>
*
* @param context The context of this evaluation.
* @param base The base object to return the most general property
* type for, or <code>null</code> to enumerate the set of
* top-level variables that this resolver can evaluate.
* @return <code>null</code> if this <code>ELResolver</code> does not
* know how to handle the given <code>base</code> object; otherwise
* <code>Object.class</code> if any type of <code>property</code>
* is accepted; otherwise the most general <code>property</code>
* type accepted for the given <code>base</code>.
*/
public abstract Class<?> getCommonPropertyType(ELContext context,
Object base);
/**
* Converts an object to a specific type.
*
* <p>An <code>ELException</code> is thrown if an error occurs during
* the conversion.</p>
*
* @param context The context of this evaluation.
* @param obj The object to convert.
* @param targetType The target type for the convertion.
* @throws ELException thrown if errors occur.
*/
public Object convertToType(ELContext context,
Object obj,
Class<?> targetType) {
return null;
}
}