package com.softwaremill.common.cdi.el; import com.softwaremill.common.util.ClassUtil; import javax.el.*; import javax.enterprise.inject.spi.BeanManager; import java.beans.FeatureDescriptor; import java.util.HashMap; import java.util.Iterator; import java.util.Map; /** * @author Adam Warski (adam at warski dot org) * @author http://community.jboss.org/thread/148045?tstart=0 */ public class TemporaryContextELEvaluator extends AbstractELEvaluator { private final ExpressionFactory expressionFactory; private final ELContext elContext; private final ConstantResolver constantResolver; public TemporaryContextELEvaluator(BeanManager beanManager) { constantResolver = new ConstantResolver(); ExpressionFactory tempExpressionFactory; try { tempExpressionFactory = ExpressionFactory.newInstance(); } catch (RuntimeException e) { tempExpressionFactory = ClassUtil.newInstance("com.sun.el.ExpressionFactoryImpl", ExpressionFactory.class); } expressionFactory = beanManager.wrapExpressionFactory(tempExpressionFactory); elContext = createELContext(beanManager); } public <T> T evaluate(String expression, Class<T> expectedResultType) { return ELEvaluatorUtil.evaluate(elContext, expressionFactory, expression, expectedResultType); } public void setParameter(String name, Object value) { constantResolver.addConstant(name, value); } public void clearParameter(String name) { constantResolver.removeConstant(name); } private ELContext createELContext(BeanManager beanManager) { return createELContext(createELResolver(beanManager), ClassUtil.newInstance(FUNCTION_MAPPER_IMPL_CLASSNAME, FunctionMapper.class), ClassUtil.newInstance(VARIABLE_MAPPER_IMPL_CLASSNAME, VariableMapper.class)); } private ELResolver createELResolver(BeanManager beanManager) { CompositeELResolver resolver = new CompositeELResolver(); resolver.add(beanManager.getELResolver()); resolver.add(new MapELResolver()); resolver.add(new ListELResolver()); resolver.add(new ArrayELResolver()); resolver.add(new ResourceBundleELResolver()); resolver.add(new BeanELResolver()); resolver.add(constantResolver); return resolver; } private ELContext createELContext(final ELResolver resolver, final FunctionMapper functionMapper, final VariableMapper variableMapper) { return new ELContext() { @Override public ELResolver getELResolver() { return resolver; } @Override public FunctionMapper getFunctionMapper() { return functionMapper; } @Override public VariableMapper getVariableMapper() { return variableMapper; } }; } private static class ConstantResolver extends ELResolver { private final Map<String, Object> constants = new HashMap<String, Object>(); public void addConstant(String name, Object value) { constants.put(name, value); } public void removeConstant(String name) { constants.remove(name); } @Override public Object getValue(ELContext context, Object base, Object property) { if (base == null && constants.containsKey(property)) { context.setPropertyResolved(true); return constants.get(property); } return null; } @Override public Class<?> getType(ELContext context, Object base, Object property) { if (base == null && constants.containsKey(property)) { return constants.get(property).getClass(); } return null; } @Override public void setValue(ELContext context, Object base, Object property, Object value) { throw new UnsupportedOperationException(); } @Override public boolean isReadOnly(ELContext context, Object base, Object property) { return true; } @Override public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context, Object base) { return null; } @Override public Class<?> getCommonPropertyType(ELContext context, Object base) { return null; } } // private final static String FUNCTION_MAPPER_IMPL_CLASSNAME; private final static String VARIABLE_MAPPER_IMPL_CLASSNAME; static { FUNCTION_MAPPER_IMPL_CLASSNAME = ClassUtil.findClassPresentInClasspath( "com.sun.el.lang.FunctionMapperImpl", "org.apache.el.lang.FunctionMapperImpl"); VARIABLE_MAPPER_IMPL_CLASSNAME = ClassUtil.findClassPresentInClasspath( "com.sun.el.lang.VariableMapperImpl", "org.apache.el.lang.VariableMapperImpl"); } }