Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: ognl/Ognl.java


1   //--------------------------------------------------------------------------
2   //  Copyright (c) 1998-2004, Drew Davidson and Luke Blanshard
3   //  All rights reserved.
4   //
5   //  Redistribution and use in source and binary forms, with or without
6   //  modification, are permitted provided that the following conditions are
7   //  met:
8   //
9   //  Redistributions of source code must retain the above copyright notice,
10  //  this list of conditions and the following disclaimer.
11  //  Redistributions in binary form must reproduce the above copyright
12  //  notice, this list of conditions and the following disclaimer in the
13  //  documentation and/or other materials provided with the distribution.
14  //  Neither the name of the Drew Davidson nor the names of its contributors
15  //  may be used to endorse or promote products derived from this software
16  //  without specific prior written permission.
17  //
18  //  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  //  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  //  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21  //  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22  //  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23  //  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24  //  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
25  //  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26  //  AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27  //  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
28  //  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
29  //  DAMAGE.
30  //--------------------------------------------------------------------------
31  package ognl;
32  
33  import java.io.StringReader;
34  import java.util.Map;
35  
36  /**
37   * <P>This class provides static methods for parsing and interpreting OGNL expressions.</P>
38   *
39   * <P>The simplest use of the Ognl class is to get the value of an expression from
40   * an object, without extra context or pre-parsing.</P>
41   *
42   * <PRE>
43   * import ognl.Ognl;
44   * import ognl.OgnlException;
45   *
46   *    try {
47   *        result = Ognl.getValue(expression, root);
48   *    } catch (OgnlException ex) {
49   *       // Report error or recover
50   *    }
51   * </PRE>
52   *
53   * <P>This will parse the expression given and evaluate it against the root object
54   * given, returning the result.  If there is an error in the expression, such
55   * as the property is not found, the exception is encapsulated into an
56   * {@link ognl.OgnlException OgnlException}.</P>
57   *
58   * <P>Other more sophisticated uses of Ognl can pre-parse expressions.  This
59   * provides two advantages: in the case of user-supplied expressions it
60   * allows you to catch parse errors before evaluation and it allows you to
61   * cache parsed expressions into an AST for better speed during repeated use.
62   * The pre-parsed expression is always returned as an <CODE>Object</CODE>
63   * to simplify use for programs that just wish to store the value for
64   * repeated use and do not care that it is an AST.  If it does care
65   * it can always safely cast the value to an <CODE>AST</CODE> type.</P>
66   *
67   * <P>The Ognl class also takes a <I>context map</I> as one of the parameters
68   * to the set and get methods.  This allows you to put your own variables
69   * into the available namespace for OGNL expressions.  The default context
70   * contains only the <CODE>#root</CODE> and <CODE>#context</CODE> keys,
71   * which are required to be present.  The <CODE>addDefaultContext(Object, Map)</CODE>
72   * method will alter an existing <CODE>Map</CODE> to put the defaults in.
73   * Here is an example that shows how to extract the <CODE>documentName</CODE>
74   * property out of the root object and append a string with the current user
75   * name in parens:</P>
76   *
77   * <PRE>
78   *     private Map  context = new HashMap();
79   *
80   *     public void setUserName(String value)
81   *     {
82   *         context.put("userName", value);
83   *     }
84   *
85   *     try {
86   *        // get value using our own custom context map
87   *        result = Ognl.getValue("documentName + \" (\" + ((#userName == null) ? \"&lt;nobody&gt;\" : #userName) + \")\"", context, root);
88   *     } catch (OgnlException ex) {
89   *         // Report error or recover
90   *     }
91   *
92   * </PRE>
93   *
94   * @author Luke Blanshard (blanshlu@netscape.net)
95   * @author Drew Davidson (drew@ognl.org)
96   * @version 27 June 1999
97   */
98  public abstract class Ognl
99  {
100       /**
101        * Parses the given OGNL expression and returns a tree representation of the
102        * expression that can be used by <CODE>Ognl</CODE> static methods.
103        *
104        * @param expression the OGNL expression to be parsed
105        * @return a tree representation of the expression
106        * @throws ExpressionSyntaxException if the expression is malformed
107        * @throws OgnlException if there is a pathological environmental problem
108        */
109     public static Object parseExpression( String expression ) throws OgnlException
110     {
111         try {
112             OgnlParser parser = new OgnlParser( new StringReader(expression) );
113             return parser.topLevelExpression();
114         }
115         catch (ParseException e) {
116             throw new ExpressionSyntaxException( expression, e );
117         }
118         catch (TokenMgrError e) {
119             throw new ExpressionSyntaxException( expression, e );
120         }
121     }
122 
123       /**
124        * Creates and returns a new standard naming context for evaluating an OGNL
125        * expression.
126        *
127        * @param root the root of the object graph
128        * @return a new Map with the keys <CODE>root</CODE> and <CODE>context</CODE>
129        *         set appropriately
130        */
131     public static Map createDefaultContext( Object root )
132     {
133         return addDefaultContext( root, null, null, null, new OgnlContext() );
134     }
135 
136       /**
137        * Creates and returns a new standard naming context for evaluating an OGNL
138        * expression.
139        *
140        * @param root the root of the object graph
141        * @return a new OgnlContext with the keys <CODE>root</CODE> and <CODE>context</CODE>
142        *         set appropriately
143        */
144     public static Map createDefaultContext( Object root, ClassResolver classResolver )
145     {
146         return addDefaultContext( root, classResolver, null, null, new OgnlContext() );
147     }
148 
149       /**
150        * Creates and returns a new standard naming context for evaluating an OGNL
151        * expression.
152        *
153        * @param root the root of the object graph
154        * @return a new Map with the keys <CODE>root</CODE> and <CODE>context</CODE>
155        *         set appropriately
156        */
157     public static Map createDefaultContext( Object root, ClassResolver classResolver, TypeConverter converter )
158     {
159         return addDefaultContext( root, classResolver, converter, null, new OgnlContext() );
160     }
161 
162       /**
163        * Creates and returns a new standard naming context for evaluating an OGNL
164        * expression.
165        *
166        * @param root the root of the object graph
167        * @return a new Map with the keys <CODE>root</CODE> and <CODE>context</CODE>
168        *         set appropriately
169        */
170     public static Map createDefaultContext( Object root, ClassResolver classResolver, TypeConverter converter, MemberAccess memberAccess )
171     {
172         return addDefaultContext( root, classResolver, converter, memberAccess, new OgnlContext() );
173     }
174 
175       /**
176        * Appends the standard naming context for evaluating an OGNL expression
177        * into the context given so that cached maps can be used as a context.
178        *
179        * @param root the root of the object graph
180        * @param context the context to which OGNL context will be added.
181        * @return Context Map with the keys <CODE>root</CODE> and <CODE>context</CODE>
182        *         set appropriately
183        */
184     public static Map addDefaultContext( Object root, Map context )
185     {
186       return addDefaultContext( root, null, null, null, context );
187     }
188 
189       /**
190        * Appends the standard naming context for evaluating an OGNL expression
191        * into the context given so that cached maps can be used as a context.
192        *
193        * @param root the root of the object graph
194        * @param context the context to which OGNL context will be added.
195        * @return Context Map with the keys <CODE>root</CODE> and <CODE>context</CODE>
196        *         set appropriately
197        */
198     public static Map addDefaultContext( Object root, ClassResolver classResolver, Map context )
199     {
200         return addDefaultContext(root, classResolver, null, null, context);
201     }
202 
203       /**
204        * Appends the standard naming context for evaluating an OGNL expression
205        * into the context given so that cached maps can be used as a context.
206        *
207        * @param root the root of the object graph
208        * @param context the context to which OGNL context will be added.
209        * @return Context Map with the keys <CODE>root</CODE> and <CODE>context</CODE>
210        *         set appropriately
211        */
212     public static Map addDefaultContext( Object root, ClassResolver classResolver, TypeConverter converter, Map context )
213     {
214         return addDefaultContext(root, classResolver, converter, null, context);
215     }
216 
217       /**
218        * Appends the standard naming context for evaluating an OGNL expression
219        * into the context given so that cached maps can be used as a context.
220        *
221        * @param root the root of the object graph
222        * @param context the context to which OGNL context will be added.
223        * @return Context Map with the keys <CODE>root</CODE> and <CODE>context</CODE>
224        *         set appropriately
225        */
226     public static Map addDefaultContext( Object root, ClassResolver classResolver, TypeConverter converter, MemberAccess memberAccess, Map context )
227     {
228         OgnlContext     result;
229 
230         if (!(context instanceof OgnlContext)) {
231             result = new OgnlContext();
232             result.setValues(context);
233         } else {
234             result = (OgnlContext)context;
235         }
236         if (classResolver != null) {
237             result.setClassResolver(classResolver);
238         }
239         if (converter != null) {
240             result.setTypeConverter(converter);
241         }
242         if (memberAccess != null) {
243             result.setMemberAccess(memberAccess);
244         }
245         result.setRoot(root);
246         return result;
247     }
248 
249     public static void setClassResolver( Map context, ClassResolver classResolver)
250     {
251         context.put(OgnlContext.CLASS_RESOLVER_CONTEXT_KEY, classResolver);
252     }
253 
254     public static ClassResolver getClassResolver( Map context )
255     {
256         return (ClassResolver)context.get(OgnlContext.CLASS_RESOLVER_CONTEXT_KEY);
257     }
258 
259     public static void setTypeConverter( Map context, TypeConverter converter)
260     {
261         context.put(OgnlContext.TYPE_CONVERTER_CONTEXT_KEY, converter);
262     }
263 
264     public static TypeConverter getTypeConverter( Map context )
265     {
266         return (TypeConverter)context.get(OgnlContext.TYPE_CONVERTER_CONTEXT_KEY);
267     }
268 
269   public static void setMemberAccess(Map context, MemberAccess memberAccess)
270   {
271       context.put(OgnlContext.MEMBER_ACCESS_CONTEXT_KEY, memberAccess);
272   }
273 
274   public static MemberAccess getMemberAccess(Map context)
275   {
276       return (MemberAccess)context.get(OgnlContext.MEMBER_ACCESS_CONTEXT_KEY);
277   }
278 
279     public static void setRoot( Map context, Object root)
280     {
281         context.put(OgnlContext.ROOT_CONTEXT_KEY, root);
282     }
283 
284     public static Object getRoot( Map context )
285     {
286         return context.get(OgnlContext.ROOT_CONTEXT_KEY);
287     }
288 
289     public static Evaluation getLastEvaluation( Map context )
290     {
291         return (Evaluation)context.get(OgnlContext.LAST_EVALUATION_CONTEXT_KEY);
292     }
293 
294       /**
295        * Evaluates the given OGNL expression tree to extract a value from the given root
296        * object. The default context is set for the given context and root via
297        * <CODE>addDefaultContext()</CODE>.
298        *
299        * @param tree the OGNL expression tree to evaluate, as returned by parseExpression()
300        * @param context the naming context for the evaluation
301        * @param root the root object for the OGNL expression
302        * @return the result of evaluating the expression
303        * @throws MethodFailedException if the expression called a method which failed
304        * @throws NoSuchPropertyException if the expression referred to a nonexistent property
305        * @throws InappropriateExpressionException if the expression can't be used in this context
306        * @throws OgnlException if there is a pathological environmental problem
307        */
308     public static Object getValue( Object tree, Map context, Object root ) throws OgnlException
309     {
310         return getValue( tree, context, root, null );
311     }
312 
313       /**
314        * Evaluates the given OGNL expression tree to extract a value from the given root
315        * object. The default context is set for the given context and root via
316        * <CODE>addDefaultContext()</CODE>.
317        *
318        * @param tree the OGNL expression tree to evaluate, as returned by parseExpression()
319        * @param context the naming context for the evaluation
320        * @param root the root object for the OGNL expression
321        * @param resultType the converted type of the resultant object, using the context's type converter
322        * @return the result of evaluating the expression
323        * @throws MethodFailedException if the expression called a method which failed
324        * @throws NoSuchPropertyException if the expression referred to a nonexistent property
325        * @throws InappropriateExpressionException if the expression can't be used in this context
326        * @throws OgnlException if there is a pathological environmental problem
327        */
328     public static Object getValue( Object tree, Map context, Object root, Class resultType ) throws OgnlException
329     {
330         Object          result;
331         OgnlContext     ognlContext = (OgnlContext)addDefaultContext(root, context);
332 
333         result = ((Node)tree).getValue( ognlContext, root );
334         if (resultType != null) {
335             result = getTypeConverter( context ).convertValue( context, root, null, null, result, resultType);
336         }
337         return result;
338     }
339 
340       /**
341        * Evaluates the given OGNL expression to extract a value from the given root
342        * object in a given context
343        *
344        * @see #parseExpression(String)
345        * @see #getValue(Object,Object)
346        * @param expression the OGNL expression to be parsed
347        * @param context the naming context for the evaluation
348        * @param root the root object for the OGNL expression
349        * @return the result of evaluating the expression
350        * @throws MethodFailedException if the expression called a method which failed
351        * @throws NoSuchPropertyException if the expression referred to a nonexistent property
352        * @throws InappropriateExpressionException if the expression can't be used in this context
353        * @throws OgnlException if there is a pathological environmental problem
354        */
355     public static Object getValue( String expression, Map context, Object root ) throws OgnlException
356     {
357         return getValue( expression, context, root, null );
358     }
359 
360       /**
361        * Evaluates the given OGNL expression to extract a value from the given root
362        * object in a given context
363        *
364        * @see #parseExpression(String)
365        * @see #getValue(Object,Object)
366        * @param expression the OGNL expression to be parsed
367        * @param context the naming context for the evaluation
368        * @param root the root object for the OGNL expression
369        * @param resultType the converted type of the resultant object, using the context's type converter
370        * @return the result of evaluating the expression
371        * @throws MethodFailedException if the expression called a method which failed
372        * @throws NoSuchPropertyException if the expression referred to a nonexistent property
373        * @throws InappropriateExpressionException if the expression can't be used in this context
374        * @throws OgnlException if there is a pathological environmental problem
375        */
376     public static Object getValue( String expression, Map context, Object root, Class resultType ) throws OgnlException
377     {
378         return getValue( parseExpression(expression), context, root, resultType );
379     }
380 
381       /**
382        * Evaluates the given OGNL expression tree to extract a value from the given root
383        * object.
384        *
385        * @param tree the OGNL expression tree to evaluate, as returned by parseExpression()
386        * @param root the root object for the OGNL expression
387        * @return the result of evaluating the expression
388        * @throws MethodFailedException if the expression called a method which failed
389        * @throws NoSuchPropertyException if the expression referred to a nonexistent property
390        * @throws InappropriateExpressionException if the expression can't be used in this context
391        * @throws OgnlException if there is a pathological environmental problem
392        */
393     public static Object getValue( Object tree, Object root ) throws OgnlException
394     {
395         return getValue( tree, root, null );
396     }
397 
398       /**
399        * Evaluates the given OGNL expression tree to extract a value from the given root
400        * object.
401        *
402        * @param tree the OGNL expression tree to evaluate, as returned by parseExpression()
403        * @param root the root object for the OGNL expression
404        * @param resultType the converted type of the resultant object, using the context's type converter
405        * @return the result of evaluating the expression
406        * @throws MethodFailedException if the expression called a method which failed
407        * @throws NoSuchPropertyException if the expression referred to a nonexistent property
408        * @throws InappropriateExpressionException if the expression can't be used in this context
409        * @throws OgnlException if there is a pathological environmental problem
410        */
411     public static Object getValue( Object tree, Object root, Class resultType ) throws OgnlException
412     {
413         return getValue( tree, createDefaultContext(root), root, resultType );
414     }
415 
416       /**
417        * Convenience method that combines calls to <code> parseExpression </code> and
418        * <code> getValue</code>.
419        *
420        * @see #parseExpression(String)
421        * @see #getValue(Object,Object)
422        * @param expression the OGNL expression to be parsed
423        * @param root the root object for the OGNL expression
424        * @return the result of evaluating the expression
425        * @throws ExpressionSyntaxException if the expression is malformed
426        * @throws MethodFailedException if the expression called a method which failed
427        * @throws NoSuchPropertyException if the expression referred to a nonexistent property
428        * @throws InappropriateExpressionException if the expression can't be used in this context
429        * @throws OgnlException if there is a pathological environmental problem
430        */
431     public static Object getValue( String expression, Object root ) throws OgnlException
432     {
433         return getValue( expression, root, null );
434     }
435 
436       /**
437        * Convenience method that combines calls to <code> parseExpression </code> and
438        * <code> getValue</code>.
439        *
440        * @see #parseExpression(String)
441        * @see #getValue(Object,Object)
442        * @param expression the OGNL expression to be parsed
443        * @param root the root object for the OGNL expression
444        * @param resultType the converted type of the resultant object, using the context's type converter
445        * @return the result of evaluating the expression
446        * @throws ExpressionSyntaxException if the expression is malformed
447        * @throws MethodFailedException if the expression called a method which failed
448        * @throws NoSuchPropertyException if the expression referred to a nonexistent property
449        * @throws InappropriateExpressionException if the expression can't be used in this context
450        * @throws OgnlException if there is a pathological environmental problem
451        */
452     public static Object getValue( String expression, Object root, Class resultType ) throws OgnlException
453     {
454         return getValue( parseExpression(expression), root, resultType );
455     }
456 
457       /**
458        * Evaluates the given OGNL expression tree to insert a value into the object graph
459        * rooted at the given root object.  The default context is set for the given
460        * context and root via <CODE>addDefaultContext()</CODE>.
461        *
462        * @param tree the OGNL expression tree to evaluate, as returned by parseExpression()
463        * @param context the naming context for the evaluation
464        * @param root the root object for the OGNL expression
465        * @param value the value to insert into the object graph
466        * @throws MethodFailedException if the expression called a method which failed
467        * @throws NoSuchPropertyException if the expression referred to a nonexistent property
468        * @throws InappropriateExpressionException if the expression can't be used in this context
469        * @throws OgnlException if there is a pathological environmental problem
470        */
471     public static void setValue( Object tree, Map context, Object root, Object value ) throws OgnlException
472     {
473         OgnlContext     ognlContext = (OgnlContext)addDefaultContext(root, context);
474         Node            n = (Node) tree;
475 
476         n.setValue( ognlContext, root, value );
477     }
478 
479       /**
480        * Evaluates the given OGNL expression to insert a value into the object graph
481        * rooted at the given root object given the context.
482        *
483        * @param expression the OGNL expression to be parsed
484        * @param root the root object for the OGNL expression
485        * @param context the naming context for the evaluation
486        * @param value the value to insert into the object graph
487        * @throws MethodFailedException if the expression called a method which failed
488        * @throws NoSuchPropertyException if the expression referred to a nonexistent property
489        * @throws InappropriateExpressionException if the expression can't be used in this context
490        * @throws OgnlException if there is a pathological environmental problem
491        */
492     public static void setValue( String expression, Map context, Object root, Object value ) throws OgnlException
493     {
494         setValue( parseExpression(expression), context, root, value );
495     }
496 
497       /**
498        * Evaluates the given OGNL expression tree to insert a value into the object graph
499        * rooted at the given root object.
500        *
501        * @param tree the OGNL expression tree to evaluate, as returned by parseExpression()
502        * @param root the root object for the OGNL expression
503        * @param value the value to insert into the object graph
504        * @throws MethodFailedException if the expression called a method which failed
505        * @throws NoSuchPropertyException if the expression referred to a nonexistent property
506        * @throws InappropriateExpressionException if the expression can't be used in this context
507        * @throws OgnlException if there is a pathological environmental problem
508        */
509     public static void setValue( Object tree, Object root, Object value ) throws OgnlException
510     {
511         setValue( tree, createDefaultContext(root), root, value );
512     }
513 
514       /**
515        * Convenience method that combines calls to <code> parseExpression </code> and
516        * <code> setValue</code>.
517        *
518        * @see #parseExpression(String)
519        * @see #setValue(Object,Object,Object)
520        * @param expression the OGNL expression to be parsed
521        * @param root the root object for the OGNL expression
522        * @param value the value to insert into the object graph
523        * @throws ExpressionSyntaxException if the expression is malformed
524        * @throws MethodFailedException if the expression called a method which failed
525        * @throws NoSuchPropertyException if the expression referred to a nonexistent property
526        * @throws InappropriateExpressionException if the expression can't be used in this context
527        * @throws OgnlException if there is a pathological environmental problem
528        */
529     public static void setValue( String expression, Object root, Object value ) throws OgnlException
530     {
531         setValue( parseExpression(expression), root, value );
532     }
533 
534     public static boolean isConstant( Object tree, Map context ) throws OgnlException
535     {
536         return ((SimpleNode)tree).isConstant( (OgnlContext)addDefaultContext( null, context ) );
537     }
538 
539     public static boolean isConstant( String expression, Map context ) throws OgnlException
540     {
541         return isConstant(parseExpression(expression), context);
542     }
543 
544     public static boolean isConstant( Object tree ) throws OgnlException
545     {
546         return isConstant(tree, createDefaultContext(null));
547     }
548 
549     public static boolean isConstant( String expression ) throws OgnlException
550     {
551         return isConstant(parseExpression(expression), createDefaultContext(null));
552     }
553 
554     public static boolean isSimpleProperty( Object tree, Map context ) throws OgnlException
555     {
556         return ((SimpleNode)tree).isSimpleProperty( (OgnlContext)addDefaultContext( null, context ) );
557     }
558 
559     public static boolean isSimpleProperty( String expression, Map context ) throws OgnlException
560     {
561         return isSimpleProperty(parseExpression(expression), context);
562     }
563 
564     public static boolean isSimpleProperty( Object tree ) throws OgnlException
565     {
566         return isSimpleProperty(tree, createDefaultContext(null));
567     }
568 
569     public static boolean isSimpleProperty( String expression ) throws OgnlException
570     {
571         return isSimpleProperty(parseExpression(expression), createDefaultContext(null));
572     }
573 
574     public static boolean isSimpleNavigationChain( Object tree, Map context ) throws OgnlException
575     {
576         return ((SimpleNode)tree).isSimpleNavigationChain( (OgnlContext)addDefaultContext( null, context ) );
577     }
578 
579     public static boolean isSimpleNavigationChain( String expression, Map context ) throws OgnlException
580     {
581         return isSimpleNavigationChain(parseExpression(expression), context);
582     }
583 
584     public static boolean isSimpleNavigationChain( Object tree ) throws OgnlException
585     {
586         return isSimpleNavigationChain(tree, createDefaultContext(null));
587     }
588 
589     public static boolean isSimpleNavigationChain( String expression ) throws OgnlException
590     {
591         return isSimpleNavigationChain(parseExpression(expression), createDefaultContext(null));
592     }
593 
594       /** You can't make one of these. */
595     private Ognl()
596     {
597     }
598 }