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 }