Skip to content

Package: MethodExpressionImpl

MethodExpressionImpl

nameinstructionbranchcomplexitylinemethod
MethodExpressionImpl()
M: 3 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
MethodExpressionImpl(String, Node, FunctionMapper, VariableMapper, Class, Class[])
M: 21 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 8 C: 0
0%
M: 1 C: 0
0%
equals(Object)
M: 14 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%
getExpressionString()
M: 3 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
getMethodInfo(ELContext)
M: 14 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
getNode()
M: 11 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 3 C: 0
0%
M: 1 C: 0
0%
hashCode()
M: 4 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
invoke(ELContext, Object[])
M: 27 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 5 C: 0
0%
M: 1 C: 0
0%
isLiteralText()
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%
isParametersProvided()
M: 4 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
readExternal(ObjectInput)
M: 32 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 8 C: 0
0%
M: 1 C: 0
0%
writeExternal(ObjectOutput)
M: 28 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 6 C: 0
0%
M: 1 C: 0
0%

Coverage

1: /*
2: * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
3: *
4: * This program and the accompanying materials are made available under the
5: * terms of the Eclipse Public License v. 2.0, which is available at
6: * http://www.eclipse.org/legal/epl-2.0.
7: *
8: * This Source Code may also be made available under the following Secondary
9: * Licenses when the conditions for such availability set forth in the
10: * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
11: * version 2 with the GNU Classpath Exception, which is available at
12: * https://www.gnu.org/software/classpath/license.html.
13: *
14: * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15: */
16:
17: package com.sun.el;
18:
19: import static com.sun.el.util.ReflectionUtil.forName;
20: import static com.sun.el.util.ReflectionUtil.toTypeArray;
21: import static com.sun.el.util.ReflectionUtil.toTypeNameArray;
22:
23: import java.io.Externalizable;
24: import java.io.IOException;
25: import java.io.ObjectInput;
26: import java.io.ObjectOutput;
27:
28: import jakarta.el.ELContext;
29: import jakarta.el.ELException;
30: import jakarta.el.ELResolver;
31: import jakarta.el.Expression;
32: import jakarta.el.ExpressionFactory;
33: import jakarta.el.FunctionMapper;
34: import jakarta.el.MethodExpression;
35: import jakarta.el.MethodInfo;
36: import jakarta.el.MethodNotFoundException;
37: import jakarta.el.PropertyNotFoundException;
38: import jakarta.el.VariableMapper;
39:
40: import com.sun.el.lang.EvaluationContext;
41: import com.sun.el.lang.ExpressionBuilder;
42: import com.sun.el.parser.Node;
43:
44: /**
45: * An <code>Expression</code> that refers to a method on an object.
46: *
47: * <p>
48: * The {@link ExpressionFactory#createMethodExpression} method can be used to parse an expression string and return a
49: * concrete instance of <code>MethodExpression</code> that encapsulates the parsed expression. The
50: * {@link FunctionMapper} is used at parse time, not evaluation time, so one is not needed to evaluate an expression
51: * using this class. However, the {@link ELContext} is needed at evaluation time.
52: * </p>
53: *
54: * <p>
55: * The {@link #getMethodInfo} and {@link #invoke} methods will evaluate the expression each time they are called. The
56: * {@link ELResolver} in the <code>ELContext</code> is used to resolve the top-level variables and to determine the
57: * behavior of the <code>.</code> and <code>[]</code> operators. For any of the two methods, the
58: * {@link ELResolver#getValue} method is used to resolve all properties up to but excluding the last one. This provides
59: * the <code>base</code> object on which the method appears. If the <code>base</code> object is null, a
60: * <code>NullPointerException</code> must be thrown. At the last resolution, the final <code>property</code> is then
61: * coerced to a <code>String</code>, which provides the name of the method to be found. A method matching the name and
62: * expected parameters provided at parse time is found and it is either queried or invoked (depending on the method
63: * called on this <code>MethodExpression</code>).
64: * </p>
65: *
66: * <p>
67: * See the notes about comparison, serialization and immutability in the {@link Expression} javadocs.
68: *
69: * @see ELResolver
70: * @see Expression
71: * @see ExpressionFactory
72: * @see MethodExpression
73: *
74: * @author Jacob Hookom [jacob@hookom.net]
75: * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $
76: */
77: public final class MethodExpressionImpl extends MethodExpression implements Externalizable {
78:
79: private Class<?> expectedType;
80: private String expr;
81: private FunctionMapper fnMapper;
82: private VariableMapper varMapper;
83: private Class<?>[] paramTypes;
84:
85: private transient Node node;
86:
87: public MethodExpressionImpl() {
88: super();
89: }
90:
91: /**
92: * @param expr the expression
93: * @param node the node
94: * @param fnMapper the function mapper
95: * @param varMapper the variable mapper
96: * @param expectedType expected return type of method
97: * @param paramTypes the method parameters
98: */
99: public MethodExpressionImpl(String expr, Node node, FunctionMapper fnMapper, VariableMapper varMapper, Class<?> expectedType, Class<?>[] paramTypes) {
100: super();
101: this.expr = expr;
102: this.node = node;
103: this.fnMapper = fnMapper;
104: this.varMapper = varMapper;
105: this.expectedType = expectedType;
106: this.paramTypes = paramTypes;
107: }
108:
109: /**
110: * Determines whether the specified object is equal to this <code>Expression</code>.
111: *
112: * <p>
113: * The result is <code>true</code> if and only if the argument is not <code>null</code>, is an <code>Expression</code>
114: * object that is the of the same type (<code>ValueExpression</code> or <code>MethodExpression</code>), and has an
115: * identical parsed representation.
116: * </p>
117: *
118: * <p>
119: * Note that two expressions can be equal if their expression Strings are different. For example,
120: * <code>${fn1:foo()}</code> and <code>${fn2:foo()}</code> are equal if their corresponding <code>FunctionMapper</code>s
121: * mapped <code>fn1:foo</code> and <code>fn2:foo</code> to the same method.
122: * </p>
123: *
124: * @param obj the <code>Object</code> to test for equality.
125: * @return <code>true</code> if <code>obj</code> equals this <code>Expression</code> <code>false</code> otherwise.
126: * @see java.util.Hashtable
127: * @see java.lang.Object#equals(java.lang.Object)
128: */
129: @Override
130: public boolean equals(Object obj) {
131:• if (obj instanceof MethodExpressionImpl) {
132: MethodExpressionImpl methodExpressionImpl = (MethodExpressionImpl) obj;
133: return getNode().equals(methodExpressionImpl.getNode());
134: }
135:
136: return false;
137: }
138:
139: /**
140: * Returns the original String used to create this <code>Expression</code>, unmodified.
141: *
142: * <p>
143: * This is used for debugging purposes but also for the purposes of comparison (e.g. to ensure the expression in a
144: * configuration file has not changed).
145: * </p>
146: *
147: * <p>
148: * This method does not provide sufficient information to re-create an expression. Two different expressions can have
149: * exactly the same expression string but different function mappings. Serialization should be used to save and restore
150: * the state of an <code>Expression</code>.
151: * </p>
152: *
153: * @return The original expression String.
154: *
155: * @see Expression#getExpressionString()
156: */
157: @Override
158: public String getExpressionString() {
159: return expr;
160: }
161:
162: /**
163: * Evaluates the expression relative to the provided context, and returns information about the actual referenced
164: * method.
165: *
166: * @param context The context of this evaluation
167: * @return an instance of <code>MethodInfo</code> containing information about the method the expression evaluated to.
168: * @throws NullPointerException if context is <code>null</code> or the base object is <code>null</code> on the last
169: * resolution.
170: * @throws PropertyNotFoundException if one of the property resolutions failed because a specified variable or property
171: * does not exist or is not readable.
172: * @throws MethodNotFoundException if no suitable method can be found.
173: * @throws ELException if an exception was thrown while performing property or variable resolution. The thrown exception
174: * must be included as the cause property of this exception, if available.
175: * @see MethodExpression#getMethodInfo(ELContext)
176: */
177: @Override
178: public MethodInfo getMethodInfo(ELContext context) throws PropertyNotFoundException, MethodNotFoundException, ELException {
179: return getNode().getMethodInfo(new EvaluationContext(context, fnMapper, varMapper), paramTypes);
180: }
181:
182: /**
183: * @return The Node for the expression
184: * @throws ELException
185: */
186: private Node getNode() throws ELException {
187:• if (node == null) {
188: node = ExpressionBuilder.createNode(expr);
189: }
190:
191: return node;
192: }
193:
194: /**
195: * Returns the hash code for this <code>Expression</code>.
196: *
197: * <p>
198: * See the note in the {@link #equals} method on how two expressions can be equal if their expression Strings are
199: * different. Recall that if two objects are equal according to the <code>equals(Object)</code> method, then calling the
200: * <code>hashCode</code> method on each of the two objects must produce the same integer result. Implementations must
201: * take special note and implement <code>hashCode</code> correctly.
202: * </p>
203: *
204: * @return The hash code for this <code>Expression</code>.
205: * @see #equals
206: * @see java.util.Hashtable
207: * @see java.lang.Object#hashCode()
208: */
209: @Override
210: public int hashCode() {
211: return getNode().hashCode();
212: }
213:
214: /**
215: * Evaluates the expression relative to the provided context, invokes the method that was found using the supplied
216: * parameters, and returns the result of the method invocation.
217: *
218: * @param context The context of this evaluation.
219: * @param params The parameters to pass to the method, or <code>null</code> if no parameters.
220: * @return the result of the method invocation (<code>null</code> if the method has a <code>void</code> return type).
221: * @throws NullPointerException if context is <code>null</code> or the base object is <code>null</code> on the last
222: * resolution.
223: * @throws PropertyNotFoundException if one of the property resolutions failed because a specified variable or property
224: * does not exist or is not readable.
225: * @throws MethodNotFoundException if no suitable method can be found.
226: * @throws ELException if an exception was thrown while performing property or variable resolution. The thrown exception
227: * must be included as the cause property of this exception, if available. If the exception thrown is an
228: * <code>InvocationTargetException</code>, extract its <code>cause</code> and pass it to the <code>ELException</code>
229: * constructor.
230: * @see MethodExpression#invoke(ELContext, java.lang.Object[])
231: */
232: @Override
233: public Object invoke(ELContext context, Object[] params) throws PropertyNotFoundException, MethodNotFoundException, ELException {
234: EvaluationContext ctx = new EvaluationContext(context, fnMapper, varMapper);
235: ctx.notifyBeforeEvaluation(expr);
236:
237: Object obj = getNode().invoke(ctx, paramTypes, params);
238:
239: ctx.notifyAfterEvaluation(expr);
240: return obj;
241: }
242:
243: /*
244: * (non-Javadoc)
245: *
246: * @see java.io.Externalizable#readExternal(java.io.ObjectInput)
247: */
248: @Override
249: public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
250: expr = in.readUTF();
251: String type = in.readUTF();
252:
253:• if (!"".equals(type)) {
254: expectedType = forName(type);
255: }
256:
257: paramTypes = toTypeArray(((String[]) in.readObject()));
258: fnMapper = (FunctionMapper) in.readObject();
259: varMapper = (VariableMapper) in.readObject();
260: }
261:
262: /*
263: * (non-Javadoc)
264: *
265: * @see java.io.Externalizable#writeExternal(java.io.ObjectOutput)
266: */
267: @Override
268: public void writeExternal(ObjectOutput out) throws IOException {
269: out.writeUTF(expr);
270:• out.writeUTF(expectedType != null ? expectedType.getName() : "");
271: out.writeObject(toTypeNameArray(paramTypes));
272: out.writeObject(fnMapper);
273: out.writeObject(varMapper);
274: }
275:
276: @Override
277: public boolean isLiteralText() {
278: return false;
279: }
280:
281: @Override
282: public boolean isParametersProvided() {
283: return getNode().isParametersProvided();
284: }
285: }