001    package org.apache.commons.ognl;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one
005     * or more contributor license agreements.  See the NOTICE file
006     * distributed with this work for additional information
007     * regarding copyright ownership.  The ASF licenses this file
008     * to you under the Apache License, Version 2.0 (the
009     * "License"); you may not use this file except in compliance
010     * with the License.  You may obtain a copy of the License at
011     *
012     *   http://www.apache.org/licenses/LICENSE-2.0
013     *
014     * Unless required by applicable law or agreed to in writing,
015     * software distributed under the License is distributed on an
016     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017     * KIND, either express or implied.  See the License for the
018     * specific language governing permissions and limitations
019     * under the License.
020     */
021    
022    import org.apache.commons.ognl.enhance.ExpressionAccessor;
023    
024    import java.io.StringReader;
025    import java.util.Map;
026    
027    /**
028     * <p>
029     * This class provides static methods for parsing and interpreting OGNL expressions.
030     * </p>
031     * <p>
032     * The simplest use of the Ognl class is to get the value of an expression from an object, without extra context or
033     * pre-parsing.
034     * </p>
035     * 
036     * <pre>
037     * 
038     * import org.apache.commons.ognl.Ognl;
039     * import org.apache.commons.ognl.OgnlException;
040     * ...
041     * try
042     * {
043     *     result = Ognl.getValue( expression, root );
044     * }
045     * catch ( OgnlException ex )
046     * {
047     *     // Report error or recover
048     * }
049     * 
050     * </pre>
051     * <p>
052     * This will parse the expression given and evaluate it against the root object given, returning the result. If there is
053     * an error in the expression, such as the property is not found, the exception is encapsulated into an
054     * {@link org.apache.commons.ognl.OgnlException OgnlException}.
055     * </p>
056     * <p>
057     * Other more sophisticated uses of Ognl can pre-parse expressions. This provides two advantages: in the case of
058     * user-supplied expressions it allows you to catch parse errors before evaluation and it allows you to cache parsed
059     * expressions into an AST for better speed during repeated use. The pre-parsed expression is always returned as an
060     * <code>Object</code> to simplify use for programs that just wish to store the value for repeated use and do not care
061     * that it is an AST. If it does care it can always safely cast the value to an <code>AST</code> type.
062     * </p>
063     * <p>
064     * The Ognl class also takes a <I>context map</I> as one of the parameters to the set and get methods. This allows you
065     * to put your own variables into the available namespace for OGNL expressions. The default context contains only the
066     * <code>#root</code> and <code>#context</code> keys, which are required to be present. The
067     * <code>addDefaultContext(Object, Map)</code> method will alter an existing <code>Map</code> to put the defaults in.
068     * Here is an example that shows how to extract the <code>documentName</code> property out of the root object and append
069     * a string with the current user name in parens:
070     * </p>
071     * 
072     * <pre>
073     * 
074     * private Map&lt;String, Object&gt; context = new HashMap&lt;String, Object&gt;();
075     * ...
076     * public void setUserName( String value )
077     * {
078     *     context.put("userName", value);
079     * }
080     * ...
081     * try
082     * {
083     *     // get value using our own custom context map
084     *     result = Ognl.getValue( "documentName + \" (\" + ((#userName == null) ? \"&lt;nobody&gt;\" : #userName ) +
085     * \")\"", context, root );
086     * }
087     * catch ( OgnlException ex )
088     * {
089     *     // Report error or recover
090     * }
091     * 
092     * </pre>
093     * 
094     * @author Luke Blanshard (blanshlu@netscape.net)
095     * @author Drew Davidson (drew@ognl.org)
096     * @version 27 June 1999
097     */
098    public abstract class Ognl
099    {
100    
101        /**
102         * Parses the given OGNL expression and returns a tree representation of the expression that can be used by
103         * <code>Ognl</code> static methods.
104         * 
105         * @param expression the OGNL expression to be parsed
106         * @return a tree representation of the expression
107         * @throws ExpressionSyntaxException if the expression is malformed
108         * @throws OgnlException if there is a pathological environmental problem
109         */
110        public static Object parseExpression( String expression )
111            throws OgnlException
112        {
113            try
114            {
115                OgnlParser parser = new OgnlParser( new StringReader( expression ) );
116                return parser.topLevelExpression();
117            }
118            catch ( ParseException e )
119            {
120                throw new ExpressionSyntaxException( expression, e );
121            }
122            catch ( TokenMgrError e )
123            {
124                throw new ExpressionSyntaxException( expression, e );
125            }
126        }
127    
128        /**
129         * Parses and compiles the given expression using the {@link org.apache.commons.ognl.enhance.OgnlExpressionCompiler}
130         * returned from
131         * {@link org.apache.commons.ognl.OgnlRuntime#getCompiler(OgnlContext)}.
132         * 
133         * @param context The context to use.
134         * @param root The root object for the given expression.
135         * @param expression The expression to compile.
136         * @return The node with a compiled accessor set on {@link org.apache.commons.ognl.Node#getAccessor()} if
137         * compilation was successfull.
138         *         In instances where compilation wasn't possible because of a partially null expression the
139         *         {@link ExpressionAccessor} instance may be null and the compilation of this expression still possible at
140         *         some as yet indertermined point in the future.
141         * @throws Exception If a compilation error occurs.
142         */
143        public static Node compileExpression( OgnlContext context, Object root, String expression )
144            throws Exception
145        {
146            Node expr = (Node) Ognl.parseExpression( expression );
147    
148            OgnlRuntime.compileExpression( context, expr, root );
149    
150            return expr;
151        }
152    
153        /**
154         * Creates and returns a new standard naming context for evaluating an OGNL expression.
155         * 
156         * @param root the root of the object graph
157         * @return a new Map with the keys <code>root</code> and <code>context</code> set appropriately
158         */
159        public static Map<String, Object> createDefaultContext( Object root )
160        {
161            return addDefaultContext( root, null, null, null, new OgnlContext() );
162        }
163    
164        /**
165         * Creates and returns a new standard naming context for evaluating an OGNL expression.
166         * 
167         * @param root The root of the object graph.
168         * @param classResolver The resolver used to instantiate {@link Class} instances referenced in the expression.
169         * @return a new OgnlContext with the keys <code>root</code> and <code>context</code> set appropriately
170         */
171        public static Map<String, Object> createDefaultContext( Object root, ClassResolver classResolver )
172        {
173            return addDefaultContext( root, classResolver, null, null, new OgnlContext() );
174        }
175    
176        /**
177         * Creates and returns a new standard naming context for evaluating an OGNL expression.
178         * 
179         * @param root The root of the object graph.
180         * @param classResolver The resolver used to instantiate {@link Class} instances referenced in the expression.
181         * @param converter Converter used to convert return types of an expression in to their desired types.
182         * @return a new Map with the keys <code>root</code> and <code>context</code> set appropriately
183         */
184        public static Map<String, Object> createDefaultContext( Object root, ClassResolver classResolver,
185                                                                TypeConverter converter )
186        {
187            return addDefaultContext( root, classResolver, converter, null, new OgnlContext() );
188        }
189    
190        /**
191         * Creates and returns a new standard naming context for evaluating an OGNL expression.
192         * 
193         * @param root The root of the object graph.
194         * @param classResolver The resolver used to instantiate {@link Class} instances referenced in the expression.
195         * @param converter Converter used to convert return types of an expression in to their desired types.
196         * @param memberAccess Java security handling object to determine semantics for accessing normally private/protected
197         *            methods / fields.
198         * @return a new Map with the keys <code>root</code> and <code>context</code> set appropriately
199         */
200        public static Map<String, Object> createDefaultContext( Object root, ClassResolver classResolver,
201                                                                TypeConverter converter, MemberAccess memberAccess )
202        {
203            return addDefaultContext( root, classResolver, converter, memberAccess, new OgnlContext() );
204        }
205    
206        /**
207         * Appends the standard naming context for evaluating an OGNL expression into the context given so that cached maps
208         * can be used as a context.
209         * 
210         * @param root the root of the object graph
211         * @param context the context to which OGNL context will be added.
212         * @return Context Map with the keys <code>root</code> and <code>context</code> set appropriately
213         */
214        public static Map<String, Object> addDefaultContext( Object root, Map<String, Object> context )
215        {
216            return addDefaultContext( root, null, null, null, context );
217        }
218    
219        /**
220         * Appends the standard naming context for evaluating an OGNL expression into the context given so that cached maps
221         * can be used as a context.
222         * 
223         * @param root The root of the object graph.
224         * @param classResolver The resolver used to instantiate {@link Class} instances referenced in the expression.
225         * @param context The context to which OGNL context will be added.
226         * @return Context Map with the keys <code>root</code> and <code>context</code> set appropriately
227         */
228        public static Map<String, Object> addDefaultContext( Object root, ClassResolver classResolver,
229                                                             Map<String, Object> context )
230        {
231            return addDefaultContext( root, classResolver, null, null, context );
232        }
233    
234        /**
235         * Appends the standard naming context for evaluating an OGNL expression into the context given so that cached maps
236         * can be used as a context.
237         * 
238         * @param root The root of the object graph.
239         * @param classResolver The resolver used to instantiate {@link Class} instances referenced in the expression.
240         * @param converter Converter used to convert return types of an expression in to their desired types.
241         * @param context The context to which OGNL context will be added.
242         * @return Context Map with the keys <code>root</code> and <code>context</code> set appropriately
243         */
244        public static Map<String, Object> addDefaultContext( Object root, ClassResolver classResolver,
245                                                             TypeConverter converter, Map<String, Object> context )
246        {
247            return addDefaultContext( root, classResolver, converter, null, context );
248        }
249    
250        /**
251         * Appends the standard naming context for evaluating an OGNL expression into the context given so that cached maps
252         * can be used as a context.
253         * 
254         * @param root the root of the object graph
255         * @param classResolver The class loading resolver that should be used to resolve class references.
256         * @param converter The type converter to be used by default.
257         * @param memberAccess Definition for handling private/protected access.
258         * @param context Default context to use, if not an {@link OgnlContext} will be dumped into a new
259         *            {@link OgnlContext} object.
260         * @return Context Map with the keys <code>root</code> and <code>context</code> set appropriately
261         */
262        public static Map<String, Object> addDefaultContext( Object root, ClassResolver classResolver,
263                                                             TypeConverter converter, MemberAccess memberAccess,
264                                                             Map<String, Object> context )
265        {
266            OgnlContext result;
267    
268            if ( !( context instanceof OgnlContext ) )
269            {
270                result = new OgnlContext();
271                result.setValues( context );
272            }
273            else
274            {
275                result = (OgnlContext) context;
276            }
277            if ( classResolver != null )
278            {
279                result.setClassResolver( classResolver );
280            }
281            if ( converter != null )
282            {
283                result.setTypeConverter( converter );
284            }
285            if ( memberAccess != null )
286            {
287                result.setMemberAccess( memberAccess );
288            }
289    
290            result.setRoot( root );
291            return result;
292        }
293    
294        /**
295         * Configures the {@link ClassResolver} to use for the given context. Will be used during expression parsing /
296         * execution to resolve class names.
297         * 
298         * @param context The context to place the resolver.
299         * @param classResolver The resolver to use to resolve classes.
300         */
301        public static void setClassResolver( Map<String, Object> context, ClassResolver classResolver )
302        {
303            context.put( OgnlContext.CLASS_RESOLVER_CONTEXT_KEY, classResolver );
304        }
305    
306        /**
307         * Gets the previously stored {@link ClassResolver} for the given context - if any.
308         * 
309         * @param context The context to get the configured resolver from.
310         * @return The resolver instance, or null if none found.
311         */
312        public static ClassResolver getClassResolver( Map<String, Object> context )
313        {
314            return (ClassResolver) context.get( OgnlContext.CLASS_RESOLVER_CONTEXT_KEY );
315        }
316    
317        /**
318         * Configures the type converter to use for a given context. This will be used to convert into / out of various java
319         * class types.
320         * 
321         * @param context The context to configure it for.
322         * @param converter The converter to use.
323         */
324        public static void setTypeConverter( Map<String, Object> context, TypeConverter converter )
325        {
326            context.put( OgnlContext.TYPE_CONVERTER_CONTEXT_KEY, converter );
327        }
328    
329        /**
330         * Gets the currently configured {@link TypeConverter} for the given context - if any.
331         * 
332         * @param context The context to get the converter from.
333         * @return The converter - or null if none found.
334         */
335        public static TypeConverter getTypeConverter( Map<String, Object> context )
336        {
337            return (TypeConverter) context.get( OgnlContext.TYPE_CONVERTER_CONTEXT_KEY );
338        }
339    
340        /**
341         * Configures the specified context with a {@link MemberAccess} instance for handling field/method protection
342         * levels.
343         * 
344         * @param context The context to configure.
345         * @param memberAccess The access resolver to configure the context with.
346         */
347        public static void setMemberAccess( Map<String, Object> context, MemberAccess memberAccess )
348        {
349            context.put( OgnlContext.MEMBER_ACCESS_CONTEXT_KEY, memberAccess );
350        }
351    
352        /**
353         * Gets the currently stored {@link MemberAccess} object for the given context - if any.
354         * 
355         * @param context The context to get the object from.
356         * @return The configured {@link MemberAccess} instance in the specified context - or null if none found.
357         */
358        public static MemberAccess getMemberAccess( Map<String, Object> context )
359        {
360            return (MemberAccess) context.get( OgnlContext.MEMBER_ACCESS_CONTEXT_KEY );
361        }
362    
363        /**
364         * Sets the root object to use for all expressions in the given context - doesn't necessarily replace root object
365         * instances explicitly passed in to other expression resolving methods on this class.
366         * 
367         * @param context The context to store the root object in.
368         * @param root The root object.
369         */
370        public static void setRoot( Map<String, Object> context, Object root )
371        {
372            context.put( OgnlContext.ROOT_CONTEXT_KEY, root );
373        }
374    
375        /**
376         * Gets the stored root object for the given context - if any.
377         * 
378         * @param context The context to get the root object from.
379         * @return The root object - or null if none found.
380         */
381        public static Object getRoot( Map<String, Object> context )
382        {
383            return context.get( OgnlContext.ROOT_CONTEXT_KEY );
384        }
385    
386        /**
387         * Gets the last {@link Evaluation} executed on the given context.
388         * 
389         * @param context The context to get the evaluation from.
390         * @return The {@link Evaluation} - or null if none was found.
391         */
392        public static Evaluation getLastEvaluation( Map<String, Object> context )
393        {
394            return (Evaluation) context.get( OgnlContext.LAST_EVALUATION_CONTEXT_KEY );
395        }
396    
397        /**
398         * Evaluates the given OGNL expression tree to extract a value from the given root object. The default context is
399         * set for the given context and root via <code>addDefaultContext()</code>.
400         * 
401         * @param tree the OGNL expression tree to evaluate, as returned by parseExpression()
402         * @param context the naming context for the evaluation
403         * @param root the root object for the OGNL expression
404         * @return the result of evaluating the expression
405         * @throws MethodFailedException if the expression called a method which failed
406         * @throws NoSuchPropertyException if the expression referred to a nonexistent property
407         * @throws InappropriateExpressionException if the expression can't be used in this context
408         * @throws OgnlException if there is a pathological environmental problem
409         */
410        public static <T> T getValue( Object tree, Map<String, Object> context, Object root )
411            throws OgnlException
412        {
413            return Ognl.<T> getValue( tree, context, root, null );
414        }
415    
416        /**
417         * Evaluates the given OGNL expression tree to extract a value from the given root object. The default context is
418         * set for the given context and root via <code>addDefaultContext()</code>.
419         * 
420         * @param tree the OGNL expression tree to evaluate, as returned by parseExpression()
421         * @param context the naming context for the evaluation
422         * @param root the root object for the OGNL expression
423         * @param resultType the converted type of the resultant object, using the context's type converter
424         * @return the result of evaluating the expression
425         * @throws MethodFailedException if the expression called a method which failed
426         * @throws NoSuchPropertyException if the expression referred to a nonexistent property
427         * @throws InappropriateExpressionException if the expression can't be used in this context
428         * @throws OgnlException if there is a pathological environmental problem
429         */
430        @SuppressWarnings( "unchecked" ) // will cause CCE if types are not compatible
431        public static <T> T getValue( Object tree, Map<String, Object> context, Object root, Class<T> resultType )
432            throws OgnlException
433        {
434            T result;
435            OgnlContext ognlContext = (OgnlContext) addDefaultContext( root, context );
436    
437            Node node = (Node) tree;
438    
439            if ( node.getAccessor() != null )
440            {
441                result = (T) node.getAccessor().get( ognlContext, root );
442            }
443            else
444            {
445                result = (T) node.getValue( ognlContext, root );
446            }
447    
448            if ( resultType != null )
449            {
450                result = getTypeConverter( context ).convertValue( context, root, null, null, result, resultType );
451            }
452            return result;
453        }
454    
455        /**
456         * Gets the value represented by the given pre-compiled expression on the specified root object.
457         * 
458         * @param expression The pre-compiled expression, as found in {@link Node#getAccessor()}.
459         * @param context The ognl context.
460         * @param root The object to retrieve the expression value from.
461         * @return The value.
462         */
463        @SuppressWarnings( "unchecked" ) // will cause CCE if types are not compatible
464        public static <T> T getValue( ExpressionAccessor expression, OgnlContext context, Object root )
465        {
466            return (T) expression.get( context, root );
467        }
468    
469        /**
470         * Gets the value represented by the given pre-compiled expression on the specified root object.
471         * 
472         * @param expression The pre-compiled expression, as found in {@link Node#getAccessor()}.
473         * @param context The ognl context.
474         * @param root The object to retrieve the expression value from.
475         * @param resultType The desired object type that the return value should be converted to using the
476         *            {@link #getTypeConverter(java.util.Map)} .
477         * @return The value.
478         */
479        public static <T> T getValue( ExpressionAccessor expression, OgnlContext context, Object root, Class<T> resultType )
480            throws OgnlException
481        {
482            return getTypeConverter( context ).convertValue( context, root, null, null, expression.get( context, root ),
483                                                             resultType );
484        }
485    
486        /**
487         * Evaluates the given OGNL expression to extract a value from the given root object in a given context
488         * 
489         * @see #parseExpression(String)
490         * @see #getValue(Object,Object)
491         * @param expression the OGNL expression to be parsed
492         * @param context the naming context for the evaluation
493         * @param root the root object for the OGNL expression
494         * @return the result of evaluating the expression
495         * @throws MethodFailedException if the expression called a method which failed
496         * @throws NoSuchPropertyException if the expression referred to a nonexistent property
497         * @throws InappropriateExpressionException if the expression can't be used in this context
498         * @throws OgnlException if there is a pathological environmental problem
499         */
500        public static <T> T getValue( String expression, Map<String, Object> context, Object root )
501            throws OgnlException
502        {
503            return Ognl.<T> getValue( expression, context, root, null );
504        }
505    
506        /**
507         * Evaluates the given OGNL expression to extract a value from the given root object in a given context
508         * 
509         * @see #parseExpression(String)
510         * @see #getValue(Object,Object)
511         * @param expression the OGNL expression to be parsed
512         * @param context the naming context for the evaluation
513         * @param root the root object for the OGNL expression
514         * @param resultType the converted type of the resultant object, using the context's type converter
515         * @return the result of evaluating the expression
516         * @throws MethodFailedException if the expression called a method which failed
517         * @throws NoSuchPropertyException if the expression referred to a nonexistent property
518         * @throws InappropriateExpressionException if the expression can't be used in this context
519         * @throws OgnlException if there is a pathological environmental problem
520         */
521        public static <T> T getValue( String expression, Map<String, Object> context, Object root, Class<T> resultType )
522            throws OgnlException
523        {
524            return Ognl.<T> getValue( parseExpression( expression ), context, root, resultType );
525        }
526    
527        /**
528         * Evaluates the given OGNL expression tree to extract a value from the given root object.
529         * 
530         * @param tree the OGNL expression tree to evaluate, as returned by parseExpression()
531         * @param root the root object for the OGNL expression
532         * @return the result of evaluating the expression
533         * @throws MethodFailedException if the expression called a method which failed
534         * @throws NoSuchPropertyException if the expression referred to a nonexistent property
535         * @throws InappropriateExpressionException if the expression can't be used in this context
536         * @throws OgnlException if there is a pathological environmental problem
537         */
538        public static <T> T getValue( Object tree, Object root )
539            throws OgnlException
540        {
541            return Ognl.<T> getValue( tree, root, null );
542        }
543    
544        /**
545         * Evaluates the given OGNL expression tree to extract a value from the given root object.
546         * 
547         * @param tree the OGNL expression tree to evaluate, as returned by parseExpression()
548         * @param root the root object for the OGNL expression
549         * @param resultType the converted type of the resultant object, using the context's type converter
550         * @return the result of evaluating the expression
551         * @throws MethodFailedException if the expression called a method which failed
552         * @throws NoSuchPropertyException if the expression referred to a nonexistent property
553         * @throws InappropriateExpressionException if the expression can't be used in this context
554         * @throws OgnlException if there is a pathological environmental problem
555         */
556        public static <T> T getValue( Object tree, Object root, Class<T> resultType )
557            throws OgnlException
558        {
559            return Ognl.<T> getValue( tree, createDefaultContext( root ), root, resultType );
560        }
561    
562        /**
563         * Convenience method that combines calls to <code> parseExpression </code> and <code> getValue</code>.
564         * 
565         * @see #parseExpression(String)
566         * @see #getValue(Object,Object)
567         * @param expression the OGNL expression to be parsed
568         * @param root the root object for the OGNL expression
569         * @return the result of evaluating the expression
570         * @throws ExpressionSyntaxException if the expression is malformed
571         * @throws MethodFailedException if the expression called a method which failed
572         * @throws NoSuchPropertyException if the expression referred to a nonexistent property
573         * @throws InappropriateExpressionException if the expression can't be used in this context
574         * @throws OgnlException if there is a pathological environmental problem
575         */
576        public static <T> T getValue( String expression, Object root )
577            throws OgnlException
578        {
579            return Ognl.<T> getValue( expression, root, null );
580        }
581    
582        /**
583         * Convenience method that combines calls to <code> parseExpression </code> and <code> getValue</code>.
584         * 
585         * @see #parseExpression(String)
586         * @see #getValue(Object,Object)
587         * @param expression the OGNL expression to be parsed
588         * @param root the root object for the OGNL expression
589         * @param resultType the converted type of the resultant object, using the context's type converter
590         * @return the result of evaluating the expression
591         * @throws ExpressionSyntaxException if the expression is malformed
592         * @throws MethodFailedException if the expression called a method which failed
593         * @throws NoSuchPropertyException if the expression referred to a nonexistent property
594         * @throws InappropriateExpressionException if the expression can't be used in this context
595         * @throws OgnlException if there is a pathological environmental problem
596         */
597        public static <T> T getValue( String expression, Object root, Class<T> resultType )
598            throws OgnlException
599        {
600            return Ognl.<T> getValue( parseExpression( expression ), root, resultType );
601        }
602    
603        /**
604         * Evaluates the given OGNL expression tree to insert a value into the object graph rooted at the given root object.
605         * The default context is set for the given context and root via <code>addDefaultContext()</code>.
606         * 
607         * @param tree the OGNL expression tree to evaluate, as returned by parseExpression()
608         * @param context the naming context for the evaluation
609         * @param root the root object for the OGNL expression
610         * @param value the value to insert into the object graph
611         * @throws MethodFailedException if the expression called a method which failed
612         * @throws NoSuchPropertyException if the expression referred to a nonexistent property
613         * @throws InappropriateExpressionException if the expression can't be used in this context
614         * @throws OgnlException if there is a pathological environmental problem
615         */
616        public static void setValue( Object tree, Map<String, Object> context, Object root, Object value )
617            throws OgnlException
618        {
619            OgnlContext ognlContext = (OgnlContext) addDefaultContext( root, context );
620            Node n = (Node) tree;
621    
622            if ( n.getAccessor() != null )
623            {
624                n.getAccessor().set( ognlContext, root, value );
625                return;
626            }
627    
628            n.setValue( ognlContext, root, value );
629        }
630    
631        /**
632         * Sets the value given using the pre-compiled expression on the specified root object.
633         * 
634         * @param expression The pre-compiled expression, as found in {@link Node#getAccessor()}.
635         * @param context The ognl context.
636         * @param root The object to set the expression value on.
637         * @param value The value to set.
638         */
639        public static void setValue( ExpressionAccessor expression, OgnlContext context, Object root, Object value )
640        {
641            expression.set( context, root, value );
642        }
643    
644        /**
645         * Evaluates the given OGNL expression to insert a value into the object graph rooted at the given root object given
646         * the context.
647         * 
648         * @param expression the OGNL expression to be parsed
649         * @param root the root object for the OGNL expression
650         * @param context the naming context for the evaluation
651         * @param value the value to insert into the object graph
652         * @throws MethodFailedException if the expression called a method which failed
653         * @throws NoSuchPropertyException if the expression referred to a nonexistent property
654         * @throws InappropriateExpressionException if the expression can't be used in this context
655         * @throws OgnlException if there is a pathological environmental problem
656         */
657        public static void setValue( String expression, Map<String, Object> context, Object root, Object value )
658            throws OgnlException
659        {
660            setValue( parseExpression( expression ), context, root, value );
661        }
662    
663        /**
664         * Evaluates the given OGNL expression tree to insert a value into the object graph rooted at the given root object.
665         * 
666         * @param tree the OGNL expression tree to evaluate, as returned by parseExpression()
667         * @param root the root object for the OGNL expression
668         * @param value the value to insert into the object graph
669         * @throws MethodFailedException if the expression called a method which failed
670         * @throws NoSuchPropertyException if the expression referred to a nonexistent property
671         * @throws InappropriateExpressionException if the expression can't be used in this context
672         * @throws OgnlException if there is a pathological environmental problem
673         */
674        public static void setValue( Object tree, Object root, Object value )
675            throws OgnlException
676        {
677            setValue( tree, createDefaultContext( root ), root, value );
678        }
679    
680        /**
681         * Convenience method that combines calls to <code> parseExpression </code> and <code> setValue</code>.
682         * 
683         * @see #parseExpression(String)
684         * @see #setValue(Object,Object,Object)
685         * @param expression the OGNL expression to be parsed
686         * @param root the root object for the OGNL expression
687         * @param value the value to insert into the object graph
688         * @throws ExpressionSyntaxException if the expression is malformed
689         * @throws MethodFailedException if the expression called a method which failed
690         * @throws NoSuchPropertyException if the expression referred to a nonexistent property
691         * @throws InappropriateExpressionException if the expression can't be used in this context
692         * @throws OgnlException if there is a pathological environmental problem
693         */
694        public static void setValue( String expression, Object root, Object value )
695            throws OgnlException
696        {
697            setValue( parseExpression( expression ), root, value );
698        }
699    
700        /**
701         * Checks if the specified {@link Node} instance represents a constant expression.
702         * 
703         * @param tree The {@link Node} to check.
704         * @param context The context to use.
705         * @return True if the node is a constant - false otherwise.
706         * @throws OgnlException If an error occurs checking the expression.
707         */
708        public static boolean isConstant( Object tree, Map<String, Object> context )
709            throws OgnlException
710        {
711            return ( (SimpleNode) tree ).isConstant( (OgnlContext) addDefaultContext( null, context ) );
712        }
713    
714        /**
715         * Checks if the specified expression represents a constant expression.
716         * 
717         * @param expression The expression to check.
718         * @param context The context to use.
719         * @return True if the node is a constant - false otherwise.
720         * @throws OgnlException If an error occurs checking the expression.
721         */
722        public static boolean isConstant( String expression, Map<String, Object> context )
723            throws OgnlException
724        {
725            return isConstant( parseExpression( expression ), context );
726        }
727    
728        /**
729         * Same as {@link #isConstant(Object, java.util.Map)} - only the {@link Map} context is created for you.
730         * 
731         * @param tree The {@link Node} to check.
732         * @return True if the node represents a constant expression - false otherwise.
733         * @throws OgnlException If an exception occurs.
734         */
735        public static boolean isConstant( Object tree )
736            throws OgnlException
737        {
738            return isConstant( tree, createDefaultContext( null ) );
739        }
740    
741        /**
742         * Same as {@link #isConstant(String, java.util.Map)} - only the {@link Map} instance is created for you.
743         * 
744         * @param expression The expression to check.
745         * @return True if the expression represents a constant - false otherwise.
746         * @throws OgnlException If an exception occurs.
747         */
748        public static boolean isConstant( String expression )
749            throws OgnlException
750        {
751            return isConstant( parseExpression( expression ), createDefaultContext( null ) );
752        }
753    
754        public static boolean isSimpleProperty( Object tree, Map<String, Object> context )
755            throws OgnlException
756        {
757            return ( (SimpleNode) tree ).isSimpleProperty( (OgnlContext) addDefaultContext( null, context ) );
758        }
759    
760        public static boolean isSimpleProperty( String expression, Map<String, Object> context )
761            throws OgnlException
762        {
763            return isSimpleProperty( parseExpression( expression ), context );
764        }
765    
766        public static boolean isSimpleProperty( Object tree )
767            throws OgnlException
768        {
769            return isSimpleProperty( tree, createDefaultContext( null ) );
770        }
771    
772        public static boolean isSimpleProperty( String expression )
773            throws OgnlException
774        {
775            return isSimpleProperty( parseExpression( expression ), createDefaultContext( null ) );
776        }
777    
778        public static boolean isSimpleNavigationChain( Object tree, Map<String, Object> context )
779            throws OgnlException
780        {
781            return ( (SimpleNode) tree ).isSimpleNavigationChain( (OgnlContext) addDefaultContext( null, context ) );
782        }
783    
784        public static boolean isSimpleNavigationChain( String expression, Map<String, Object> context )
785            throws OgnlException
786        {
787            return isSimpleNavigationChain( parseExpression( expression ), context );
788        }
789    
790        public static boolean isSimpleNavigationChain( Object tree )
791            throws OgnlException
792        {
793            return isSimpleNavigationChain( tree, createDefaultContext( null ) );
794        }
795    
796        public static boolean isSimpleNavigationChain( String expression )
797            throws OgnlException
798        {
799            return isSimpleNavigationChain( parseExpression( expression ), createDefaultContext( null ) );
800        }
801    
802        /** You can't make one of these. */
803        private Ognl()
804        {
805        }
806    }