KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > el > MethodExpressionImpl


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the "License"). You may not use this file except
5  * in compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * glassfish/bootstrap/legal/CDDLv1.0.txt or
9  * https://glassfish.dev.java.net/public/CDDLv1.0.html.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * HEADER in each file and include the License file at
15  * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable,
16  * add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your
18  * own identifying information: Portions Copyright [yyyy]
19  * [name of copyright owner]
20  *
21  * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
22  *
23  * Portions Copyright Apache Software Foundation.
24  */

25 package com.sun.el;
26
27 import java.io.Externalizable JavaDoc;
28 import java.io.IOException JavaDoc;
29 import java.io.ObjectInput JavaDoc;
30 import java.io.ObjectOutput JavaDoc;
31
32 import javax.el.ELContext;
33 import javax.el.ELException;
34 import javax.el.ELResolver;
35 import javax.el.Expression;
36 import javax.el.ExpressionFactory;
37 import javax.el.FunctionMapper;
38 import javax.el.MethodExpression;
39 import javax.el.MethodInfo;
40 import javax.el.MethodNotFoundException;
41 import javax.el.PropertyNotFoundException;
42 import javax.el.VariableMapper;
43
44 import com.sun.el.lang.ELSupport;
45 import com.sun.el.lang.EvaluationContext;
46 import com.sun.el.lang.ExpressionBuilder;
47 import com.sun.el.parser.Node;
48 import com.sun.el.util.ReflectionUtil;
49
50 /**
51  * An <code>Expression</code> that refers to a method on an object.
52  *
53  * <p>
54  * <code>The {@link ExpressionFactory#createMethodExpression} method
55  * can be used to parse an expression string and return a concrete instance
56  * of <code>MethodExpression</code> that encapsulates the parsed expression.
57  * The {@link FunctionMapper} is used at parse time, not evaluation time,
58  * so one is not needed to evaluate an expression using this class.
59  * However, the {@link ELContext} is needed at evaluation time.</p>
60  *
61  * <p>The {@link #getMethodInfo} and {@link #invoke} methods will evaluate the
62  * expression each time they are called. The {@link ELResolver} in the
63  * <code>ELContext</code> is used to resolve the top-level variables and to
64  * determine the behavior of the <code>.</code> and <code>[]</code>
65  * operators. For any of the two methods, the {@link ELResolver#getValue}
66  * method is used to resolve all properties up to but excluding the last
67  * one. This provides the <code>base</code> object on which the method
68  * appears. If the <code>base</code> object is null, a
69  * <code>NullPointerException</code> must be thrown. At the last resolution,
70  * the final <code>property</code> is then coerced to a <code>String</code>,
71  * which provides the name of the method to be found. A method matching the
72  * name and expected parameters provided at parse time is found and it is
73  * either queried or invoked (depending on the method called on this
74  * <code>MethodExpression</code>).</p>
75  *
76  * <p>See the notes about comparison, serialization and immutability in
77  * the {@link Expression} javadocs.
78  *
79  * @see javax.el.ELResolver
80  * @see javax.el.Expression
81  * @see javax.el.ExpressionFactory
82  * @see javax.el.MethodExpression
83  *
84  * @author Jacob Hookom [jacob@hookom.net]
85  * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: kchung $
86  */

87 public final class MethodExpressionImpl extends MethodExpression implements
88         Externalizable JavaDoc {
89
90     private Class JavaDoc expectedType;
91
92     private String JavaDoc expr;
93
94     private FunctionMapper fnMapper;
95
96     private VariableMapper varMapper;
97
98     private transient Node node;
99
100     private Class JavaDoc[] paramTypes;
101
102     /**
103      *
104      */

105     public MethodExpressionImpl() {
106         super();
107     }
108
109     /**
110      * @param expr
111      * @param node
112      * @param fnMapper
113      * @param expectedType
114      * @param paramTypes
115      */

116     public MethodExpressionImpl(String JavaDoc expr, Node node,
117             FunctionMapper fnMapper, VariableMapper varMapper,
118             Class JavaDoc expectedType, Class JavaDoc[] paramTypes) {
119         super();
120         this.expr = expr;
121         this.node = node;
122         this.fnMapper = fnMapper;
123         this.varMapper = varMapper;
124         this.expectedType = expectedType;
125         this.paramTypes = paramTypes;
126     }
127
128     /**
129      * Determines whether the specified object is equal to this
130      * <code>Expression</code>.
131      *
132      * <p>
133      * The result is <code>true</code> if and only if the argument is not
134      * <code>null</code>, is an <code>Expression</code> object that is the
135      * of the same type (<code>ValueExpression</code> or
136      * <code>MethodExpression</code>), and has an identical parsed
137      * representation.
138      * </p>
139      *
140      * <p>
141      * Note that two expressions can be equal if their expression Strings are
142      * different. For example, <code>${fn1:foo()}</code> and
143      * <code>${fn2:foo()}</code> are equal if their corresponding
144      * <code>FunctionMapper</code>s mapped <code>fn1:foo</code> and
145      * <code>fn2:foo</code> to the same method.
146      * </p>
147      *
148      * @param obj
149      * the <code>Object</code> to test for equality.
150      * @return <code>true</code> if <code>obj</code> equals this
151      * <code>Expression</code>; <code>false</code> otherwise.
152      * @see java.util.Hashtable
153      * @see java.lang.Object#equals(java.lang.Object)
154      */

155     public boolean equals(Object JavaDoc obj) {
156         return (obj instanceof MethodExpressionImpl && obj.hashCode() == this
157                 .hashCode());
158     }
159
160     /**
161      * Returns the original String used to create this <code>Expression</code>,
162      * unmodified.
163      *
164      * <p>
165      * This is used for debugging purposes but also for the purposes of
166      * comparison (e.g. to ensure the expression in a configuration file has not
167      * changed).
168      * </p>
169      *
170      * <p>
171      * This method does not provide sufficient information to re-create an
172      * expression. Two different expressions can have exactly the same
173      * expression string but different function mappings. Serialization should
174      * be used to save and restore the state of an <code>Expression</code>.
175      * </p>
176      *
177      * @return The original expression String.
178      *
179      * @see javax.el.Expression#getExpressionString()
180      */

181     public String JavaDoc getExpressionString() {
182         return this.expr;
183     }
184
185     /**
186      * Evaluates the expression relative to the provided context, and returns
187      * information about the actual referenced method.
188      *
189      * @param context
190      * The context of this evaluation
191      * @return an instance of <code>MethodInfo</code> containing information
192      * about the method the expression evaluated to.
193      * @throws NullPointerException
194      * if context is <code>null</code> or the base object is
195      * <code>null</code> on the last resolution.
196      * @throws PropertyNotFoundException
197      * if one of the property resolutions failed because a specified
198      * variable or property does not exist or is not readable.
199      * @throws MethodNotFoundException
200      * if no suitable method can be found.
201      * @throws ELException
202      * if an exception was thrown while performing property or
203      * variable resolution. The thrown exception must be included as
204      * the cause property of this exception, if available.
205      * @see javax.el.MethodExpression#getMethodInfo(javax.el.ELContext)
206      */

207     public MethodInfo getMethodInfo(ELContext context)
208             throws PropertyNotFoundException, MethodNotFoundException,
209             ELException {
210         Node n = this.getNode();
211         EvaluationContext ctx = new EvaluationContext(context, this.fnMapper,
212                 this.varMapper);
213         return n.getMethodInfo(ctx, this.paramTypes);
214     }
215
216     /**
217      * @return
218      * @throws ELException
219      */

220     private Node getNode() throws ELException {
221         if (this.node == null) {
222             this.node = ExpressionBuilder.createNode(this.expr);
223         }
224         return this.node;
225     }
226
227     /**
228      * Returns the hash code for this <code>Expression</code>.
229      *
230      * <p>
231      * See the note in the {@link #equals} method on how two expressions can be
232      * equal if their expression Strings are different. Recall that if two
233      * objects are equal according to the <code>equals(Object)</code> method,
234      * then calling the <code>hashCode</code> method on each of the two
235      * objects must produce the same integer result. Implementations must take
236      * special note and implement <code>hashCode</code> correctly.
237      * </p>
238      *
239      * @return The hash code for this <code>Expression</code>.
240      * @see #equals
241      * @see java.util.Hashtable
242      * @see java.lang.Object#hashCode()
243      */

244     public int hashCode() {
245         return this.expr.hashCode();
246     }
247
248     /**
249      * Evaluates the expression relative to the provided context, invokes the
250      * method that was found using the supplied parameters, and returns the
251      * result of the method invocation.
252      *
253      * @param context
254      * The context of this evaluation.
255      * @param params
256      * The parameters to pass to the method, or <code>null</code>
257      * if no parameters.
258      * @return the result of the method invocation (<code>null</code> if the
259      * method has a <code>void</code> return type).
260      * @throws NullPointerException
261      * if context is <code>null</code> or the base object is
262      * <code>null</code> on the last resolution.
263      * @throws PropertyNotFoundException
264      * if one of the property resolutions failed because a specified
265      * variable or property does not exist or is not readable.
266      * @throws MethodNotFoundException
267      * if no suitable method can be found.
268      * @throws ELException
269      * if an exception was thrown while performing property or
270      * variable resolution. The thrown exception must be included as
271      * the cause property of this exception, if available. If the
272      * exception thrown is an <code>InvocationTargetException</code>,
273      * extract its <code>cause</code> and pass it to the
274      * <code>ELException</code> constructor.
275      * @see javax.el.MethodExpression#invoke(javax.el.ELContext,
276      * java.lang.Object[])
277      */

278     public Object JavaDoc invoke(ELContext context, Object JavaDoc[] params)
279             throws PropertyNotFoundException, MethodNotFoundException,
280             ELException {
281         EvaluationContext ctx = new EvaluationContext(context, this.fnMapper,
282                 this.varMapper);
283         return this.getNode().invoke(ctx, this.paramTypes, params);
284     }
285
286     /*
287      * (non-Javadoc)
288      *
289      * @see java.io.Externalizable#readExternal(java.io.ObjectInput)
290      */

291     public void readExternal(ObjectInput JavaDoc in) throws IOException JavaDoc,
292             ClassNotFoundException JavaDoc {
293         this.expr = in.readUTF();
294         String JavaDoc type = in.readUTF();
295         if (!"".equals(type)) {
296             this.expectedType = ReflectionUtil.forName(type);
297         }
298         this.paramTypes = ReflectionUtil.toTypeArray(((String JavaDoc[]) in
299                 .readObject()));
300         this.fnMapper = (FunctionMapper) in.readObject();
301         this.varMapper = (VariableMapper) in.readObject();
302     }
303
304     /*
305      * (non-Javadoc)
306      *
307      * @see java.io.Externalizable#writeExternal(java.io.ObjectOutput)
308      */

309     public void writeExternal(ObjectOutput JavaDoc out) throws IOException JavaDoc {
310         out.writeUTF(this.expr);
311         out.writeUTF((this.expectedType != null) ? this.expectedType.getName()
312                 : "");
313         out.writeObject(ReflectionUtil.toTypeNameArray(this.paramTypes));
314         out.writeObject(this.fnMapper);
315         out.writeObject(this.varMapper);
316     }
317
318     public boolean isLiteralText() {
319         return false;
320     }
321 }
322
Popular Tags