Skip to content

Package: ArrayELResolver

ArrayELResolver

nameinstructionbranchcomplexitylinemethod
ArrayELResolver()
M: 6 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 3 C: 0
0%
M: 1 C: 0
0%
ArrayELResolver(boolean)
M: 6 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 3 C: 0
0%
M: 1 C: 0
0%
getCommonPropertyType(ELContext, Object)
M: 10 C: 0
0%
M: 4 C: 0
0%
M: 3 C: 0
0%
M: 3 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%
getType(ELContext, Object, Object)
M: 40 C: 0
0%
M: 12 C: 0
0%
M: 7 C: 0
0%
M: 11 C: 0
0%
M: 1 C: 0
0%
getValue(ELContext, Object, Object)
M: 32 C: 0
0%
M: 10 C: 0
0%
M: 6 C: 0
0%
M: 8 C: 0
0%
M: 1 C: 0
0%
isReadOnly(ELContext, Object, Object)
M: 32 C: 0
0%
M: 10 C: 0
0%
M: 6 C: 0
0%
M: 8 C: 0
0%
M: 1 C: 0
0%
setValue(ELContext, Object, Object, Object)
M: 57 C: 0
0%
M: 16 C: 0
0%
M: 9 C: 0
0%
M: 14 C: 0
0%
M: 1 C: 0
0%
toInteger(Object)
M: 43 C: 0
0%
M: 12 C: 0
0%
M: 7 C: 0
0%
M: 11 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.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> and that this resolver was not constructed in read-only mode, this
77: * method will return <code>base.getClass().getComponentType()</code>, which is the most general type of component
78: * that can be stored at 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 which must be {@code null} if the either the property or the resolver is
87: * read-only; otherwise undefined
88: * @throws PropertyNotFoundException if the given index is out of bounds for this array.
89: * @throws NullPointerException if context is <code>null</code>
90: * @throws ELException if an exception was thrown while performing the property or variable resolution. The thrown
91: * exception must be included as the cause property of this exception, if available.
92: */
93: @Override
94: public Class<?> getType(ELContext context, Object base, Object property) {
95:
96:• if (context == null) {
97: throw new NullPointerException();
98: }
99:
100:• if (base != null && base.getClass().isArray()) {
101: context.setPropertyResolved(true);
102: int index = toInteger(property);
103:• if (index < 0 || index >= Array.getLength(base)) {
104: throw new PropertyNotFoundException();
105: }
106:
107: /*
108: * The resolver may have been created in read-only mode but the
109: * array and its elements will always be read-write.
110: */
111:• if (isReadOnly) {
112: return null;
113: }
114:
115: return base.getClass().getComponentType();
116: }
117: return null;
118: }
119:
120: /**
121: * If the base object is a Java language array, returns the value at the given index. The index is specified by the
122: * <code>property</code> argument, and coerced into an integer. If the coercion could not be performed, an
123: * <code>IllegalArgumentException</code> is thrown. If the index is out of bounds, <code>null</code> is returned.
124: *
125: * <p>
126: * If the base is a Java language array, the <code>propertyResolved</code> property of the <code>ELContext</code> object
127: * must be set to <code>true</code> by this resolver, before returning. If this property is not <code>true</code> after
128: * this method is called, the caller should ignore the return value.
129: * </p>
130: *
131: * @param context The context of this evaluation.
132: * @param base The array to analyze. Only bases that are Java language arrays are handled by this resolver.
133: * @param property The index of the value to be returned. Will be coerced into an integer.
134: * @return If the <code>propertyResolved</code> property of <code>ELContext</code> was set to <code>true</code>, then
135: * the value at the given index or <code>null</code> if the index was out of bounds. Otherwise, undefined.
136: * @throws IllegalArgumentException if the property could not be coerced into an integer.
137: * @throws NullPointerException if context is <code>null</code>.
138: * @throws ELException if an exception was thrown while performing the property or variable resolution. The thrown
139: * exception must be included as the cause property of this exception, if available.
140: */
141: @Override
142: public Object getValue(ELContext context, Object base, Object property) {
143:
144:• if (context == null) {
145: throw new NullPointerException();
146: }
147:
148:• if (base != null && base.getClass().isArray()) {
149: context.setPropertyResolved(base, property);
150: int index = toInteger(property);
151:• if (index >= 0 && index < Array.getLength(base)) {
152: return Array.get(base, index);
153: }
154: }
155: return null;
156: }
157:
158: /**
159: * If the base object is a Java language array, attempts to set the value at the given index with the given value. The
160: * index is specified by the <code>property</code> argument, and coerced into an integer. If the coercion could not be
161: * performed, an <code>IllegalArgumentException</code> is thrown. If the index is out of bounds, a
162: * <code>PropertyNotFoundException</code> is thrown.
163: *
164: * <p>
165: * If the base is a Java language array, the <code>propertyResolved</code> property of the <code>ELContext</code> object
166: * must be set to <code>true</code> by this resolver, before returning. If this property is not <code>true</code> after
167: * this method is called, the caller can safely assume no value was set.
168: * </p>
169: *
170: * <p>
171: * If this resolver was constructed in read-only mode, this method will always throw
172: * <code>PropertyNotWritableException</code>.
173: * </p>
174: *
175: * @param context The context of this evaluation.
176: * @param base The array to be modified. Only bases that are Java language arrays are handled by this resolver.
177: * @param property The index of the value to be set. Will be coerced into an integer.
178: * @param val The value to be set at the given index.
179: * @throws ClassCastException if the class of the specified element prevents it from being added to this array.
180: * @throws NullPointerException if context is <code>null</code>.
181: * @throws IllegalArgumentException if the property could not be coerced into an integer, or if some aspect of the
182: * specified element prevents it from being added to this array.
183: * @throws PropertyNotWritableException if this resolver was constructed in read-only mode.
184: * @throws PropertyNotFoundException if the given index is out of bounds for this array.
185: * @throws ELException if an exception was thrown while performing the property or variable resolution. The thrown
186: * exception must be included as the cause property of this exception, if available.
187: */
188: @Override
189: public void setValue(ELContext context, Object base, Object property, Object val) {
190:
191:• if (context == null) {
192: throw new NullPointerException();
193: }
194:
195:• if (base != null && base.getClass().isArray()) {
196: context.setPropertyResolved(base, property);
197:• if (isReadOnly) {
198: throw new PropertyNotWritableException();
199: }
200: Class<?> type = base.getClass().getComponentType();
201:• if (val != null && !type.isAssignableFrom(val.getClass())) {
202: throw new ClassCastException();
203: }
204: int index = toInteger(property);
205:• if (index < 0 || index >= Array.getLength(base)) {
206: throw new PropertyNotFoundException();
207: }
208: Array.set(base, index, val);
209: }
210: }
211:
212: /**
213: * If the base object is a Java language array, returns whether a call to {@link #setValue} will always fail.
214: *
215: * <p>
216: * If the base is a Java language array, the <code>propertyResolved</code> property of the <code>ELContext</code> object
217: * must be set to <code>true</code> by this resolver, before returning. If this property is not <code>true</code> after
218: * this method is called, the caller should ignore the return value.
219: * </p>
220: *
221: * <p>
222: * If this resolver was constructed in read-only mode, this method will always return <code>true</code>. Otherwise, it
223: * returns <code>false</code>.
224: * </p>
225: *
226: * @param context The context of this evaluation.
227: * @param base The array to analyze. Only bases that are a Java language array are handled by this resolver.
228: * @param property The index of the element in the array to return the acceptable type for. Will be coerced into an
229: * integer, but otherwise ignored by this resolver.
230: * @return If the <code>propertyResolved</code> property of <code>ELContext</code> was set to <code>true</code>, then
231: * <code>true</code> if calling the <code>setValue</code> method will always fail or <code>false</code> if it is
232: * possible that such a call may succeed; otherwise undefined.
233: * @throws PropertyNotFoundException if the given index is out of bounds for this array.
234: * @throws NullPointerException if context is <code>null</code>
235: * @throws ELException if an exception was thrown while performing the property or variable resolution. The thrown
236: * exception must be included as the cause property of this exception, if available.
237: */
238: @Override
239: public boolean isReadOnly(ELContext context, Object base, Object property) {
240:
241:• if (context == null) {
242: throw new NullPointerException();
243: }
244:
245:• if (base != null && base.getClass().isArray()) {
246: context.setPropertyResolved(true);
247: int index = toInteger(property);
248:• if (index < 0 || index >= Array.getLength(base)) {
249: throw new PropertyNotFoundException();
250: }
251: }
252: return isReadOnly;
253: }
254:
255: /**
256: * Always returns <code>null</code>, since there is no reason to iterate through set set of all integers.
257: *
258: * <p>
259: * The {@link #getCommonPropertyType} method returns sufficient information about what properties this resolver accepts.
260: * </p>
261: *
262: * @param context The context of this evaluation.
263: * @param base The array to analyze. Only bases that are a Java language array are handled by this resolver.
264: * @return <code>null</code>.
265: *
266: * @deprecated This method will be removed without replacement in EL 6.0
267: */
268: @Deprecated(forRemoval = true, since = "5.0")
269: @Override
270: public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context, Object base) {
271: return null;
272: }
273:
274: /**
275: * If the base object is a Java language array, returns the most general type that this resolver accepts for the
276: * <code>property</code> argument. Otherwise, returns <code>null</code>.
277: *
278: * <p>
279: * Assuming the base is an array, this method will always return <code>Integer.class</code>. This is because arrays
280: * accept integers for their index.
281: * </p>
282: *
283: * @param context The context of this evaluation.
284: * @param base The array to analyze. Only bases that are a Java language array are handled by this resolver.
285: * @return <code>null</code> if base is not a Java language array; otherwise <code>Integer.class</code>.
286: */
287: @Override
288: public Class<?> getCommonPropertyType(ELContext context, Object base) {
289:
290:• if (base != null && base.getClass().isArray()) {
291: return Integer.class;
292: }
293: return null;
294: }
295:
296: private int toInteger(Object p) {
297:
298:• if (p instanceof Integer) {
299: return ((Integer) p).intValue();
300: }
301:• if (p instanceof Character) {
302: return ((Character) p).charValue();
303: }
304:• if (p instanceof Boolean) {
305:• return ((Boolean) p).booleanValue() ? 1 : 0;
306: }
307:• if (p instanceof Number) {
308: return ((Number) p).intValue();
309: }
310:• if (p instanceof String) {
311: return Integer.parseInt((String) p);
312: }
313: throw new IllegalArgumentException();
314: }
315:
316: private boolean isReadOnly;
317: }