Package: ArrayELResolver
ArrayELResolver
name | instruction | branch | complexity | line | method | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
ArrayELResolver() |
|
|
|
|
|
||||||||||||||||||||
ArrayELResolver(boolean) |
|
|
|
|
|
||||||||||||||||||||
getCommonPropertyType(ELContext, Object) |
|
|
|
|
|
||||||||||||||||||||
getFeatureDescriptors(ELContext, Object) |
|
|
|
|
|
||||||||||||||||||||
getType(ELContext, Object, Object) |
|
|
|
|
|
||||||||||||||||||||
getValue(ELContext, Object, Object) |
|
|
|
|
|
||||||||||||||||||||
isReadOnly(ELContext, Object, Object) |
|
|
|
|
|
||||||||||||||||||||
setValue(ELContext, Object, Object, Object) |
|
|
|
|
|
||||||||||||||||||||
toInteger(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.lang.reflect.Array;
23: import java.util.Iterator;
24:
25: /**
26: * Defines property resolution behavior on arrays.
27: *
28: * <p>
29: * This resolver handles base objects that are Java language arrays. It accepts any object as a property and coerces
30: * that object into an integer index into the array. The resulting value is the value in the array at that index.
31: * </p>
32: *
33: * <p>
34: * This resolver can be constructed in read-only mode, which means that {@link #isReadOnly} will always return
35: * <code>true</code> and {@link #setValue} will always throw <code>PropertyNotWritableException</code>.
36: * </p>
37: *
38: * <p>
39: * <code>ELResolver</code>s are combined together using {@link CompositeELResolver}s, to define rich semantics for
40: * evaluating an expression. See the javadocs for {@link ELResolver} for details.
41: * </p>
42: *
43: * @see CompositeELResolver
44: * @see ELResolver
45: *
46: * @since Jakarta Server Pages 2.1
47: */
48: public class ArrayELResolver extends ELResolver {
49:
50: /**
51: * Creates a new read/write <code>ArrayELResolver</code>.
52: */
53: public ArrayELResolver() {
54: this.isReadOnly = false;
55: }
56:
57: /**
58: * Creates a new <code>ArrayELResolver</code> whose read-only status is determined by the given parameter.
59: *
60: * @param isReadOnly <code>true</code> if this resolver cannot modify arrays; <code>false</code> otherwise.
61: */
62: public ArrayELResolver(boolean isReadOnly) {
63: this.isReadOnly = isReadOnly;
64: }
65:
66: /**
67: * If the base object is an array, returns the most general acceptable type for a value in this array.
68: *
69: * <p>
70: * If the base is a <code>array</code>, the <code>propertyResolved</code> property of the <code>ELContext</code> object
71: * must be set to <code>true</code> by this resolver, before returning. If this property is not <code>true</code> after
72: * this method is called, the caller should ignore the return value.
73: * </p>
74: *
75: * <p>
76: * Assuming the base is an <code>array</code>, this method will always return
77: * <code>base.getClass().getComponentType()</code>, which is the most general type of component that can be stored at
78: * any given index in the array.
79: * </p>
80: *
81: * @param context The context of this evaluation.
82: * @param base The array to analyze. Only bases that are Java language arrays are handled by this resolver.
83: * @param property The index of the element in the array to return the acceptable type for. Will be coerced into an
84: * integer, but otherwise ignored by this resolver.
85: * @return If the <code>propertyResolved</code> property of <code>ELContext</code> was set to <code>true</code>, then
86: * the most general acceptable type; otherwise undefined.
87: * @throws PropertyNotFoundException if the given index is out of bounds for this array.
88: * @throws NullPointerException if context is <code>null</code>
89: * @throws ELException if an exception was thrown while performing the property or variable resolution. The thrown
90: * exception must be included as the cause property of this exception, if available.
91: */
92: @Override
93: public Class<?> getType(ELContext context, Object base, Object property) {
94:
95:• if (context == null) {
96: throw new NullPointerException();
97: }
98:
99:• if (base != null && base.getClass().isArray()) {
100: context.setPropertyResolved(true);
101: int index = toInteger(property);
102:• if (index < 0 || index >= Array.getLength(base)) {
103: throw new PropertyNotFoundException();
104: }
105: return base.getClass().getComponentType();
106: }
107: return null;
108: }
109:
110: /**
111: * If the base object is a Java language array, returns the value at the given index. The index is specified by the
112: * <code>property</code> argument, and coerced into an integer. If the coercion could not be performed, an
113: * <code>IllegalArgumentException</code> is thrown. If the index is out of bounds, <code>null</code> is returned.
114: *
115: * <p>
116: * If the base is a Java language array, the <code>propertyResolved</code> property of the <code>ELContext</code> object
117: * must be set to <code>true</code> by this resolver, before returning. If this property is not <code>true</code> after
118: * this method is called, the caller should ignore the return value.
119: * </p>
120: *
121: * @param context The context of this evaluation.
122: * @param base The array to analyze. Only bases that are Java language arrays are handled by this resolver.
123: * @param property The index of the value to be returned. Will be coerced into an integer.
124: * @return If the <code>propertyResolved</code> property of <code>ELContext</code> was set to <code>true</code>, then
125: * the value at the given index or <code>null</code> if the index was out of bounds. Otherwise, undefined.
126: * @throws IllegalArgumentException if the property could not be coerced into an integer.
127: * @throws NullPointerException if context is <code>null</code>.
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: @Override
132: public Object getValue(ELContext context, Object base, Object property) {
133:
134:• if (context == null) {
135: throw new NullPointerException();
136: }
137:
138:• if (base != null && base.getClass().isArray()) {
139: context.setPropertyResolved(base, property);
140: int index = toInteger(property);
141:• if (index >= 0 && index < Array.getLength(base)) {
142: return Array.get(base, index);
143: }
144: }
145: return null;
146: }
147:
148: /**
149: * If the base object is a Java language array, attempts to set the value at the given index with the given value. The
150: * index is specified by the <code>property</code> argument, and coerced into an integer. If the coercion could not be
151: * performed, an <code>IllegalArgumentException</code> is thrown. If the index is out of bounds, a
152: * <code>PropertyNotFoundException</code> is thrown.
153: *
154: * <p>
155: * If the base is a Java language array, the <code>propertyResolved</code> property of the <code>ELContext</code> object
156: * must be set to <code>true</code> by this resolver, before returning. If this property is not <code>true</code> after
157: * this method is called, the caller can safely assume no value was set.
158: * </p>
159: *
160: * <p>
161: * If this resolver was constructed in read-only mode, this method will always throw
162: * <code>PropertyNotWritableException</code>.
163: * </p>
164: *
165: * @param context The context of this evaluation.
166: * @param base The array to be modified. Only bases that are Java language arrays are handled by this resolver.
167: * @param property The index of the value to be set. Will be coerced into an integer.
168: * @param val The value to be set at the given index.
169: * @throws ClassCastException if the class of the specified element prevents it from being added to this array.
170: * @throws NullPointerException if context is <code>null</code>.
171: * @throws IllegalArgumentException if the property could not be coerced into an integer, or if some aspect of the
172: * specified element prevents it from being added to this array.
173: * @throws PropertyNotWritableException if this resolver was constructed in read-only mode.
174: * @throws PropertyNotFoundException if the given index is out of bounds for this array.
175: * @throws ELException if an exception was thrown while performing the property or variable resolution. The thrown
176: * exception must be included as the cause property of this exception, if available.
177: */
178: @Override
179: public void setValue(ELContext context, Object base, Object property, Object val) {
180:
181:• if (context == null) {
182: throw new NullPointerException();
183: }
184:
185:• if (base != null && base.getClass().isArray()) {
186: context.setPropertyResolved(base, property);
187:• if (isReadOnly) {
188: throw new PropertyNotWritableException();
189: }
190: Class<?> type = base.getClass().getComponentType();
191:• if (val != null && !type.isAssignableFrom(val.getClass())) {
192: throw new ClassCastException();
193: }
194: int index = toInteger(property);
195:• if (index < 0 || index >= Array.getLength(base)) {
196: throw new PropertyNotFoundException();
197: }
198: Array.set(base, index, val);
199: }
200: }
201:
202: /**
203: * If the base object is a Java language array, returns whether a call to {@link #setValue} will always fail.
204: *
205: * <p>
206: * If the base is a Java language array, the <code>propertyResolved</code> property of the <code>ELContext</code> object
207: * must be set to <code>true</code> by this resolver, before returning. If this property is not <code>true</code> after
208: * this method is called, the caller should ignore the return value.
209: * </p>
210: *
211: * <p>
212: * If this resolver was constructed in read-only mode, this method will always return <code>true</code>. Otherwise, it
213: * returns <code>false</code>.
214: * </p>
215: *
216: * @param context The context of this evaluation.
217: * @param base The array to analyze. Only bases that are a Java language array are handled by this resolver.
218: * @param property The index of the element in the array to return the acceptable type for. Will be coerced into an
219: * integer, but otherwise ignored by this resolver.
220: * @return If the <code>propertyResolved</code> property of <code>ELContext</code> was set to <code>true</code>, then
221: * <code>true</code> if calling the <code>setValue</code> method will always fail or <code>false</code> if it is
222: * possible that such a call may succeed; otherwise undefined.
223: * @throws PropertyNotFoundException if the given index is out of bounds for this array.
224: * @throws NullPointerException if context is <code>null</code>
225: * @throws ELException if an exception was thrown while performing the property or variable resolution. The thrown
226: * exception must be included as the cause property of this exception, if available.
227: */
228: @Override
229: public boolean isReadOnly(ELContext context, Object base, Object property) {
230:
231:• if (context == null) {
232: throw new NullPointerException();
233: }
234:
235:• if (base != null && base.getClass().isArray()) {
236: context.setPropertyResolved(true);
237: int index = toInteger(property);
238:• if (index < 0 || index >= Array.getLength(base)) {
239: throw new PropertyNotFoundException();
240: }
241: }
242: return isReadOnly;
243: }
244:
245: /**
246: * Always returns <code>null</code>, since there is no reason to iterate through set set of all integers.
247: *
248: * <p>
249: * The {@link #getCommonPropertyType} method returns sufficient information about what properties this resolver accepts.
250: * </p>
251: *
252: * @param context The context of this evaluation.
253: * @param base The array to analyze. Only bases that are a Java language array are handled by this resolver.
254: * @return <code>null</code>.
255: *
256: * @deprecated This method will be removed without replacement in EL 6.0
257: */
258: @Deprecated(forRemoval = true, since = "5.0")
259: @Override
260: public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context, Object base) {
261: return null;
262: }
263:
264: /**
265: * If the base object is a Java language array, returns the most general type that this resolver accepts for the
266: * <code>property</code> argument. Otherwise, returns <code>null</code>.
267: *
268: * <p>
269: * Assuming the base is an array, this method will always return <code>Integer.class</code>. This is because arrays
270: * accept integers for their index.
271: * </p>
272: *
273: * @param context The context of this evaluation.
274: * @param base The array to analyze. Only bases that are a Java language array are handled by this resolver.
275: * @return <code>null</code> if base is not a Java language array; otherwise <code>Integer.class</code>.
276: */
277: @Override
278: public Class<?> getCommonPropertyType(ELContext context, Object base) {
279:
280:• if (base != null && base.getClass().isArray()) {
281: return Integer.class;
282: }
283: return null;
284: }
285:
286: private int toInteger(Object p) {
287:
288:• if (p instanceof Integer) {
289: return ((Integer) p).intValue();
290: }
291:• if (p instanceof Character) {
292: return ((Character) p).charValue();
293: }
294:• if (p instanceof Boolean) {
295:• return ((Boolean) p).booleanValue() ? 1 : 0;
296: }
297:• if (p instanceof Number) {
298: return ((Number) p).intValue();
299: }
300:• if (p instanceof String) {
301: return Integer.parseInt((String) p);
302: }
303: throw new IllegalArgumentException();
304: }
305:
306: private boolean isReadOnly;
307: }