/* * Copyright 2011 <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.ocpsoft.rewrite.spring; import org.ocpsoft.rewrite.el.spi.ExpressionLanguageProvider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.BeanExpressionContext; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.expression.BeanExpressionContextAccessor; import org.springframework.context.expression.BeanFactoryAccessor; import org.springframework.context.expression.BeanFactoryResolver; import org.springframework.context.expression.MapAccessor; import org.springframework.context.expression.StandardBeanExpressionResolver; import org.springframework.core.convert.ConversionService; import org.springframework.expression.EvaluationContext; import org.springframework.expression.Expression; import org.springframework.expression.ExpressionParser; import org.springframework.expression.spel.SpelEvaluationException; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.expression.spel.support.StandardTypeConverter; import org.springframework.expression.spel.support.StandardTypeLocator; import org.springframework.web.context.WebApplicationContext; /** * Implementation of {@link org.ocpsoft.rewrite.el.spi.ExpressionLanguageProvider} for the Spring Expression Language * (SpEL) * * @author Christian Kaltepoth */ public class SpringExpressionLanguageProvider implements ExpressionLanguageProvider { /** * Used to parse the SpEL expressions */ private final ExpressionParser parser = new SpelExpressionParser(); @Autowired private WebApplicationContext applicationContext; @Override public int priority() { return 20; } @Override public Object retrieveValue(String expression) throws UnsupportedOperationException { try { Expression exp = parser.parseExpression(expression); return exp.getValue(getEvaluationContext()); } catch (SpelEvaluationException e) { throw new IllegalArgumentException(e); } } @Override public void submitValue(String expression, Object value) throws UnsupportedOperationException { try { Expression exp = parser.parseExpression(expression); exp.setValue(getEvaluationContext(), value); } catch (SpelEvaluationException e) { throw new IllegalArgumentException(e); } } @Override public Object evaluateMethodExpression(String expression) throws UnsupportedOperationException { try { // the method expression MUST end with () String el = expression; if (!el.endsWith("()")) { el = el + "()"; } // evaluate the expression Expression exp = parser.parseExpression(el); return exp.getValue(getEvaluationContext()); } catch (SpelEvaluationException e) { throw new UnsupportedOperationException(e); } } @Override public Object evaluateMethodExpression(String expression, Object... values) throws UnsupportedOperationException { throw new UnsupportedOperationException(); } /** * Lazily initialized by {@link #getEvaluationContext()} */ private EvaluationContext _evaluationContext = null; /** * Lazily creates a StandardEvaluationContext. The code has been inspired by * {@link StandardBeanExpressionResolver#evaluate(String, BeanExpressionContext)} */ public EvaluationContext getEvaluationContext() { if (_evaluationContext == null) { // we need a ConfigurableBeanFactory to build the BeanExpressionContext ConfigurableBeanFactory beanFactory = null; // the WebApplicationContext MAY implement ConfigurableBeanFactory if (applicationContext instanceof ConfigurableBeanFactory) { beanFactory = (ConfigurableBeanFactory) applicationContext; } // the AutowireCapableBeanFactory usually implements ConfigurableListableBeanFactory if (beanFactory == null && applicationContext != null && applicationContext.getAutowireCapableBeanFactory() instanceof ConfigurableBeanFactory) { beanFactory = (ConfigurableBeanFactory) applicationContext.getAutowireCapableBeanFactory(); } // we cannot continue without a ConfigurableBeanFactory if (beanFactory == null) { throw new IllegalStateException("Unable to find a ConfigurableBeanFactory"); } BeanExpressionContext beanEvaluationContext = new BeanExpressionContext(beanFactory, null); StandardEvaluationContext sec = new StandardEvaluationContext(); sec.setRootObject(beanEvaluationContext); sec.addPropertyAccessor(new BeanExpressionContextAccessor()); sec.addPropertyAccessor(new BeanFactoryAccessor()); sec.addPropertyAccessor(new MapAccessor()); sec.setBeanResolver(new BeanFactoryResolver(beanEvaluationContext.getBeanFactory())); sec.setTypeLocator(new StandardTypeLocator(beanEvaluationContext.getBeanFactory().getBeanClassLoader())); ConversionService conversionService = beanEvaluationContext.getBeanFactory().getConversionService(); if (conversionService != null) { sec.setTypeConverter(new StandardTypeConverter(conversionService)); } _evaluationContext = sec; } return _evaluationContext; } }