Skip to main content
This revision made July 27, 2011 21:41, by Kin-man Chung

Introduction

This is the API for using EL stand-alone, outside of a web container. ELProcessor is the main engine that EL users would be using most of the time. ELManager can be used to manage the environment/context for EL processing.

One design philosophy used here is to hide most of the implementation details from the users of this API. Things like ELContext, ELResolver, or even ValueExpression are not used. To be revisited

An instance of ELProcessor can be obtained from the ExpressionFactory. In it there is a default ELManager, which contains a default ELContext, which in term contains a default ELResolver, FunctionMapper, and VariableMapper. They are mostly empty, except for the default ELResolver, which contain enough ELResolvers to handle beans properties, arrays etc. details to be defined.

The following example shows how the api can be used.

  // Get an instance of ELProcessor.  Container can inject one too.
  ELProcess el = ExpressionFactory.newInstance().newELProcessor();
  ELManager mgr = el.getELManager();
  mgr.addBeanNameResolver(new BeanNameResolver() {
    public Object getBean(String name) {
      return myBeans.get(name);
    }
  });
  // Evaluate an EL expression
  Object bar = el.getValue("#{foo.bar}");

ELProcessor.java

/*

 * Defines an API for EL expression processing.
 */

interface ELProcessor {

    /*
     * Return the ELManager used for EL processing.
     */
    ELManager getELManager();
    /*
     * Evaluate an EL expression, without coercion.
     */
    Object getValue(String expression);
    /*
     * Evaluate an EL expression, with coercion.
     */
    Object getValue(String expression, Class expectedType);
    /*
     * Set a value to an EL expression that is a LHS
     */
    void setValue(String expression, Object value);
    /*
     * Define a EL variable
     */
    void defineVariable(String var, String expression);
    /*
     * Define a EL function
     * @param prefix The prefix of the function, or "" if prefix not used.
     * @param localName The short name of the function.
     * @param function The static fucntion e.g "org.acme.App.meth"
     * TODO: need parameters types?
     */
    void defineFunction(String prefix, String localName, String function);

}

ELManager.java

/*

 * Manages EL parsing and evaluation environment.  The ELManager maintains an
 * instance of ELContext, which is used for parsing and evaluating EL
 * expressions.  It also contains a reference to an ExpressionFactory, the
 * EL engine.  Both of these instances can be replaced.
 *
 * When Expression.newELProcessor is invoked, the standard ELManager is
 * instantiated.  The ELManager contains a standard ELContext.  See ELContext
 * for a description of the standard ELContext.
 */

interface ELManager {

    /*
     * Return the ExpressionFactory instance used for EL evaluations
     */
    ExpressionFactory getExpressionFactory();
    /*
     * Set the ExpressionFactory used for EL evaluations.
     * @return The previous ExpressionFactory, null if none
     */
    ExpressionFactory setExpressionFactory(ExpressionFactory factory);
    /*
     * Return the ELContext used.
     */
    ELContext getELContext();
    /*
     * Set the ELContext used for parsing and evaluating EL expressions.
     * @return The previous ELContext, null if none.
     */
    ELContext setELContext(ELContext context);
    /*
     * Register bean name lookup
     * Implicitly adds a BeanNameELResolver to the list of ELResolvers
     */
    void addBeanNameResolver(BeanNameResolver bnr);
    /*
     * Add user defined ELResolver to the currect list of ELResolvers
     * Can be called multiple times with additive effect.
     */
    void addELResolver(ELResolver elr);
    /*
     * Set the ELResolver in the ELContext, to be used for EL expression
     * processing.  Note that the ELResolvers added in previous calls to
     * addELResolver and addBeanNameResolver  are associated with the previous
     * ELContext, and will not be automatically added to the new ELResolver.
     * @return The previous ELResolver or null if there is none.
     */
    ELResolver setELResolver(ELResolver elr);

}

BeanNameResolver.java

/*

 * An abstract class that can be extended to return a bean object given its name
 * or to set a value to an existing bean.
 */

abstract class BeanNameResolver {

    /*
     * Return the bean known by its name
     */
    String getBean(String beanName) {
        return null;
    }
    /*
     * Set a value to an existing bean of the given name.
     */
    void setBeanValue(String beanName, Object value)
             throws PropertyNotWritableException {
        throw new PropertyNotWritableException();
    }

}

BeanNameELResolver.java

/*

 * An ELResolver that help to resolve user or container managed beans.
 */

public class BeanNameELResolver extends ELResolver {

    private BeanNameResolver beanNameResolver;
    public BeanNameELResolver(BeanNameResolver beanNameResolver) {
        this.beanNameResolver = beanNameResolver;
    }
    @Override
    public Object getValue(ELContext context, Object base, Object property) {
        if (context == null) {
            throw new NullPointerException();
        }
        if (base == null && property instanceof String) {
            Object bean = beanNameResolver.getBean((String) property);
            if (bean != null) {
                context.setPropertyResolved(true);
                return bean;
            }
        }
        return null;
    }
    @Override
    public void setValue(ELContext context, Object base, Object property,
                         Object value) {
        if (context == null) {
            throw new NullPointerException();
        }
        if (base == null && property instanceof String) {
            Object bean = beanNameResolver.getBean((String) property);
            if (bean != null) {
                context.setPropertyResolved(true);
                beanNameResolver.setBeanValue((String) property, value);
            }
        }
    }

}

ExpressionFactory.java

public abstract class ExpressionFactory {

    ...
    /*
     * Get a new instance of an implementation of ELProcessor
     */
    public abstract ELProcessor newELProcessor();

}

Difference compared to previous revision
===ELManager.java=== /* * Manages EL parsing and evaluation environment. The ELManager maintains an * instance of ELContext, which is used for parsing and evaluating EL * expressions. It also contains a reference to an ExpressionFactory, the * EL engine. Both of these instances can be replaced. * * When Expression.newELProcessor is invoked, the standard ELManager is * instantiated. The ELManager contains a standard ELContext. See ELContext * for a description of the standard ELContext. */ interface ELManager { /* ... ExpressionFactory getExpressionFactory(); /* * Set the ExpressionFactory used for EL evaluations. * @return The previous ExpressionFactory, null if none */ ExpressionFactory setExpressionFactory(ExpressionFactory factory); /* * Return the ELContext used. */ ELContext getELContext(); /* * Set the ELContext used for parsing and evaluating EL expressions. * @return The previous ELContext, null if none. */ ELContext setELContext(ELContext context); /* * Register bean name lookup * Implicitly adds a BeanNameELResolver to the list of ELResolvers */ void addBeanNameResolver(BeanNameResolver bnr); ... void addELResolver(ELResolver elr); /* * Set the ELResolver in the ELContext, to be used for EL expression * == Introduction == This is the API for using EL stand-alone, outside of a web container. ELProcessor is the main engine that EL users would be using most of the time. ELManager can be used to manage the environment/context for EL processing. ... void addELResolver(ELResolver elr); /* * Set the ELResolver to be used for EL expression processing. * processing. Note that the ELResolvers added in previous calls to * Note that the ELResolvers added in previous calls addELResolver and * addELResolver and addBeanNameResolver are associated with the previous * ELContext, and wiaddBeanNameResolver will not be automatically added to the new * ELResolver. * @return The previous ELResolver or null if there is none. */ ELResolver setELResolver(ELResolver elr);
 
 
Close
loading
Please Confirm
Close