001    // Copyright 2004, 2005 The Apache Software Foundation
002    //
003    // Licensed under the Apache License, Version 2.0 (the "License");
004    // you may not use this file except in compliance with the License.
005    // You may obtain a copy of the License at
006    //
007    //     http://www.apache.org/licenses/LICENSE-2.0
008    //
009    // Unless required by applicable law or agreed to in writing, software
010    // distributed under the License is distributed on an "AS IS" BASIS,
011    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012    // See the License for the specific language governing permissions and
013    // limitations under the License.
014    
015    package org.apache.tapestry.services.impl;
016    
017    import java.util.Iterator;
018    import java.util.List;
019    import java.util.Map;
020    
021    import ognl.ClassResolver;
022    import ognl.Ognl;
023    import ognl.OgnlRuntime;
024    import ognl.TypeConverter;
025    
026    import org.apache.hivemind.ApplicationRuntimeException;
027    import org.apache.tapestry.Tapestry;
028    import org.apache.tapestry.services.ExpressionCache;
029    import org.apache.tapestry.services.ExpressionEvaluator;
030    import org.apache.tapestry.spec.IApplicationSpecification;
031    
032    /**
033     * @author Howard M. Lewis Ship
034     * @since 4.0
035     */
036    public class ExpressionEvaluatorImpl implements ExpressionEvaluator
037    {
038        // Uses Thread's context class loader
039    
040        private final ClassResolver _ognlResolver = new OgnlClassResolver();
041    
042        private ExpressionCache _expressionCache;
043    
044        private IApplicationSpecification _applicationSpecification;
045    
046        private TypeConverter _typeConverter;
047    
048        private List _contributions;
049    
050        // Context, with a root of null, used when evaluating an expression
051        // to see if it is a constant.
052    
053        private Map _defaultContext;
054    
055        public void setApplicationSpecification(IApplicationSpecification applicationSpecification)
056        {
057            _applicationSpecification = applicationSpecification;
058        }
059    
060        public void initializeService()
061        {
062            if (_applicationSpecification.checkExtension(Tapestry.OGNL_TYPE_CONVERTER))
063                _typeConverter = (TypeConverter) _applicationSpecification.getExtension(
064                        Tapestry.OGNL_TYPE_CONVERTER,
065                        TypeConverter.class);
066    
067            Iterator i = _contributions.iterator();
068    
069            while (i.hasNext())
070            {
071                PropertyAccessorContribution c = (PropertyAccessorContribution) i.next();
072    
073                OgnlRuntime.setPropertyAccessor(c.getSubjectClass(), c.getAccessor());
074            }
075    
076            _defaultContext = Ognl.createDefaultContext(null, _ognlResolver, _typeConverter);
077    
078        }
079    
080        public Object read(Object target, String expression)
081        {
082            return readCompiled(target, _expressionCache.getCompiledExpression(expression));
083        }
084    
085        public Object readCompiled(Object target, Object expression)
086        {
087            try
088            {
089                Map context = createContext(target);
090    
091                return Ognl.getValue(expression, context, target);
092            }
093            catch (Exception ex)
094            {
095                throw new ApplicationRuntimeException(ImplMessages.unableToReadExpression(ImplMessages
096                        .parsedExpression(), target, ex), target, null, ex);
097            }
098        }
099    
100        private Map createContext(Object target)
101        {
102            Map result = Ognl.createDefaultContext(target, _ognlResolver);
103    
104            if (_typeConverter != null)
105                Ognl.setTypeConverter(result, _typeConverter);
106    
107            return result;
108        }
109    
110        public void write(Object target, String expression, Object value)
111        {
112            writeCompiled(target, _expressionCache.getCompiledExpression(expression), value);
113        }
114    
115        public void writeCompiled(Object target, Object expression, Object value)
116        {
117            try
118            {
119                Map context = createContext(target);
120    
121                Ognl.setValue(expression, context, target, value);
122            }
123            catch (Exception ex)
124            {
125                throw new ApplicationRuntimeException(ImplMessages.unableToWriteExpression(ImplMessages
126                        .parsedExpression(), target, value, ex), target, null, ex);
127            }
128    
129        }
130    
131        public boolean isConstant(String expression)
132        {
133            Object compiled = _expressionCache.getCompiledExpression(expression);
134    
135            try
136            {
137                return Ognl.isConstant(compiled, _defaultContext);
138            }
139            catch (Exception ex)
140            {
141                throw new ApplicationRuntimeException(ImplMessages.isConstantExpressionError(
142                        expression,
143                        ex), ex);
144            }
145        }
146    
147        public void setExpressionCache(ExpressionCache expressionCache)
148        {
149            _expressionCache = expressionCache;
150        }
151    
152        public void setContributions(List contributions)
153        {
154            _contributions = contributions;
155        }
156    }