Package: StaticFieldELResolver
StaticFieldELResolver
name | instruction | branch | complexity | line | method | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
StaticFieldELResolver() |
|
|
|
|
|
||||||||||||||||||||
getCommonPropertyType(ELContext, Object) |
|
|
|
|
|
||||||||||||||||||||
getFeatureDescriptors(ELContext, Object) |
|
|
|
|
|
||||||||||||||||||||
getType(ELContext, Object, Object) |
|
|
|
|
|
||||||||||||||||||||
getValue(ELContext, Object, Object) |
|
|
|
|
|
||||||||||||||||||||
invoke(ELContext, Object, Object, Class[], Object[]) |
|
|
|
|
|
||||||||||||||||||||
isReadOnly(ELContext, Object, Object) |
|
|
|
|
|
||||||||||||||||||||
setValue(ELContext, Object, Object, Object) |
|
|
|
|
|
Coverage
1: /*
2: * Copyright (c) 2012, 2021 Oracle and/or its affiliates and others.
3: * All rights reserved.
4: *
5: * This program and the accompanying materials are made available under the
6: * terms of the Eclipse Public License v. 2.0, which is available at
7: * http://www.eclipse.org/legal/epl-2.0.
8: *
9: * This Source Code may also be made available under the following Secondary
10: * Licenses when the conditions for such availability set forth in the
11: * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
12: * version 2 with the GNU Classpath Exception, which is available at
13: * https://www.gnu.org/software/classpath/license.html.
14: *
15: * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
16: */
17:
18: package jakarta.el;
19:
20: import static java.lang.reflect.Modifier.isPublic;
21: import static java.lang.reflect.Modifier.isStatic;
22: import static jakarta.el.ELUtil.getExceptionMessageString;
23:
24: import java.beans.FeatureDescriptor;
25: import java.lang.reflect.Constructor;
26: import java.lang.reflect.Field;
27: import java.lang.reflect.Method;
28: import java.util.Iterator;
29:
30: /**
31: * An {@link ELResolver} for resolving static fields, enum constants and static methods. Also handles constructor calls
32: * as a special case.
33: *
34: * <p>
35: * The resolver handles base objects of the type {@link ELClass}, which is usually generated by a Jakarta Expression
36: * Language implementation.
37: *
38: * @see ELClass
39: * @since Jakarta Expression Language 3.0
40: */
41: public class StaticFieldELResolver extends ELResolver {
42:
43: /**
44: * <p>
45: * Returns the value of a static field.
46: * </p>
47: * <p>
48: * If the base object is an instance of <code>ELClass</code> and the property is String, the
49: * <code>propertyResolved</code> property of the <code>ELContext</code> object must be set to <code>true</code> by this
50: * resolver, before returning. If this property is not <code>true</code> after this method is called, the caller should
51: * ignore the return value.
52: * </p>
53: *
54: * If the property is a public static field of class specified in <code>ELClass</code>, return the value of the static
55: * field. An Enum constant is a public static field of an Enum object, and is a special case of this.
56: *
57: * @param context The context of this evaluation.
58: * @param base An <code>ELClass</code>.
59: * @param property A static field name.
60: *
61: * @return If the <code>propertyResolved</code> property of <code>ELContext</code> was set to <code>true</code>, then
62: * the static field value.
63: *
64: * @throws NullPointerException if context is <code>null</code>.
65: * @throws PropertyNotFoundException if the specified class does not exist, or if the field is not a public static filed
66: * of the class, or if the field is inaccessible.
67: */
68: @Override
69: public Object getValue(ELContext context, Object base, Object property) {
70:• if (context == null) {
71: throw new NullPointerException();
72: }
73:
74:• if (base instanceof ELClass && property instanceof String) {
75: Class<?> klass = ((ELClass) base).getKlass();
76: String fieldName = (String) property;
77: try {
78: context.setPropertyResolved(base, property);
79: Field field = klass.getField(fieldName);
80:
81: int mod = field.getModifiers();
82:• if (isPublic(mod) && isStatic(mod)) {
83: return field.get(null);
84: }
85: } catch (NoSuchFieldException ex) {
86: } catch (IllegalAccessException ex) {
87: }
88:
89: throw new PropertyNotFoundException(getExceptionMessageString(context, "staticFieldReadError", new Object[] { klass.getName(), fieldName }));
90: }
91:
92: return null;
93: }
94:
95: /**
96: * <p>
97: * Attempts to write to a static field.
98: * </p>
99: * <p>
100: * If the base object is an instance of <code>ELClass</code>and the property is String, a
101: * <code>PropertyNotWritableException</code> will always be thrown, because writing to a static field is not allowed.
102: *
103: * @param context The context of this evaluation.
104: * @param base An <code>ELClass</code>
105: * @param property The name of the field
106: * @param value The value to set the field of the class to.
107: * @throws NullPointerException if context is <code>null</code>
108: * @throws PropertyNotWritableException if base object instance of <code>ELClass</code>and <code>property</code>
109: * instance of String
110: */
111: @Override
112: public void setValue(ELContext context, Object base, Object property, Object value) {
113:• if (context == null) {
114: throw new NullPointerException();
115: }
116:
117:• if (base instanceof ELClass && property instanceof String) {
118: Class<?> klass = ((ELClass) base).getKlass();
119: String fieldName = (String) property;
120: throw new PropertyNotWritableException(
121: getExceptionMessageString(context, "staticFieldWriteError", new Object[] { klass.getName(), fieldName }));
122: }
123: }
124:
125: /**
126: * Invokes a public static method or the constructor for a class.
127: *
128: * <p>
129: * If the base object is an instance of <code>ELClass</code> and the method is a String, the
130: * <code>propertyResolved</code> property of the <code>ELContext</code> object must be set to <code>true</code> by the
131: * resolver, before returning. If this property is not <code>true</code> after this method is called, the caller should
132: * ignore the return value.
133: *
134: * <p>
135: * Invoke the public static method specified by <code>method</code>.
136: *
137: * <p>
138: * The process involved in the method selection is the same as that used in {@link BeanELResolver}.
139: *
140: * <p>
141: * As a special case, if the name of the method is "<init>", the constructor for the class will be invoked.
142: *
143: * @param base An <code>ELClass</code>
144: * @param methodName When coerced to a <code>String</code>, the simple name of the method.
145: * @param paramTypes An array of Class objects identifying the method's formal parameter types, in declared order. Use
146: * an empty array if the method has no parameters. Can be <code>null</code>, in which case the method's formal parameter
147: * types are assumed to be unknown.
148: * @param params The parameters to pass to the method, or <code>null</code> if no parameters.
149: * @return The result of the method invocation (<code>null</code> if the method has a <code>void</code> return type).
150: * @throws MethodNotFoundException if no suitable method can be found.
151: * @throws ELException if an exception was thrown while performing (base, method) resolution. The thrown exception must
152: * be included as the cause property of this exception, if available. If the exception thrown is an
153: * <code>InvocationTargetException</code>, extract its <code>cause</code> and pass it to the <code>ELException</code>
154: * constructor.
155: */
156: @Override
157: public Object invoke(ELContext context, Object base, Object methodName, Class<?>[] paramTypes, Object[] params) {
158:• if (context == null) {
159: throw new NullPointerException();
160: }
161:
162:• if (!(base instanceof ELClass && methodName instanceof String)) {
163: return null;
164: }
165:
166: Class<?> klass = ((ELClass) base).getKlass();
167: String name = (String) methodName;
168:
169: Object ret;
170:• if ("<init>".equals(name)) {
171: Constructor<?> constructor = ELUtil.findConstructor(klass, paramTypes, params);
172: ret = ELUtil.invokeConstructor(context, constructor, params);
173: } else {
174: Method method = ELUtil.findMethod(klass, name, paramTypes, params, true);
175: ret = ELUtil.invokeMethod(context, method, null, params);
176: }
177: context.setPropertyResolved(base, methodName);
178:
179: return ret;
180: }
181:
182: /**
183: * Returns the type of a static field.
184: *
185: * <p>
186: * If the base object is an instance of <code>ELClass</code>and the property is a String, the
187: * <code>propertyResolved</code> property of the <code>ELContext</code> object must be set to <code>true</code> by the
188: * resolver, before returning. If this property is not <code>true</code> after this method is called, the caller can
189: * safely assume no value has been set.
190: *
191: * <p>
192: * If the property string is a public static field of class specified in ELClass, return the type of the static field.
193: *
194: * @param context The context of this evaluation.
195: * @param base An <code>ELClass</code>.
196: * @param property The name of the field.
197: * @return If the <code>propertyResolved</code> property of <code>ELContext</code> was set to <code>true</code>, then
198: * the type of the type of the field.
199: * @throws NullPointerException if context is <code>null</code>.
200: * @throws PropertyNotFoundException if field is not a public static filed of the class, or if the field is
201: * inaccessible.
202: */
203: @Override
204: public Class<?> getType(ELContext context, Object base, Object property) {
205:• if (context == null) {
206: throw new NullPointerException();
207: }
208:
209:• if (base instanceof ELClass && property instanceof String) {
210: Class<?> klass = ((ELClass) base).getKlass();
211: String fieldName = (String) property;
212: try {
213: context.setPropertyResolved(true);
214: Field field = klass.getField(fieldName);
215:
216: int mod = field.getModifiers();
217:• if (isPublic(mod) && isStatic(mod)) {
218: return field.getType();
219: }
220: } catch (NoSuchFieldException ex) {
221: }
222: throw new PropertyNotFoundException(getExceptionMessageString(context, "staticFieldReadError", new Object[] { klass.getName(), fieldName }));
223: }
224:
225: return null;
226: }
227:
228: /**
229: * <p>
230: * Inquires whether the static field is writable.
231: * </p>
232: * <p>
233: * If the base object is an instance of <code>ELClass</code>and the property is a String, the
234: * <code>propertyResolved</code> property of the <code>ELContext</code> object must be set to <code>true</code> by the
235: * resolver, before returning. If this property is not <code>true</code> after this method is called, the caller can
236: * safely assume no value has been set.
237: * </p>
238: *
239: * <p>
240: * Always returns a <code>true</code> because writing to a static field is not allowed.
241: * </p>
242: *
243: * @param context The context of this evaluation.
244: * @param base An <code>ELClass</code>.
245: * @param property The name of the bean.
246: * @return <code>true</code>
247: * @throws NullPointerException if context is <code>null</code>.
248: */
249: @Override
250: public boolean isReadOnly(ELContext context, Object base, Object property) {
251:• if (context == null) {
252: throw new NullPointerException();
253: }
254:
255:• if (base instanceof ELClass && property instanceof String) {
256: ((ELClass) base).getKlass();
257: context.setPropertyResolved(true);
258: }
259:
260: return true;
261: }
262:
263: /**
264: * Returns the properties that can be resolved. Always returns <code>null</code>, since there is no reason to iterate
265: * through a list of one element: field name.
266: *
267: * @param context The context of this evaluation.
268: * @param base An <code>ELClass</code>.
269: * @return <code>null</code>.
270: *
271: * @deprecated This method will be removed without replacement in EL 6.0
272: */
273: @Deprecated(forRemoval = true, since = "5.0")
274: @Override
275: public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context, Object base) {
276: return null;
277: }
278:
279: /**
280: * Returns the type of the property. Always returns <code>String.class</code>, since a field name is a String.
281: *
282: * @param context The context of this evaluation.
283: * @param base An <code>ELClass</code>.
284: * @return <code>String.class</code>.
285: */
286: @Override
287: public Class<?> getCommonPropertyType(ELContext context, Object base) {
288: return String.class;
289: }
290: }